blob: 7888e5aa1cae7d1fc8690b4ff3122608f67d038c [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
386 if (out->routing_change) {
387 out->routing_change = false;
388 // must be checked for backward compatibility
389 if (adev->adm_on_routing_change)
390 adev->adm_on_routing_change(adev->adm_data, out->handle);
391 }
392
393 if (adev->adm_request_focus_v2)
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 else if (adev->adm_request_focus)
396 adev->adm_request_focus(adev->adm_data, out->handle);
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
403 if (in->routing_change) {
404 in->routing_change = false;
405 if (adev->adm_on_routing_change)
406 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
407 }
408
409 if (adev->adm_request_focus_v2)
410 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
411 else if (adev->adm_request_focus)
412 adev->adm_request_focus(adev->adm_data, in->capture_handle);
413}
414
415static void release_out_focus(struct stream_out *out)
416{
417 struct audio_device *adev = out->dev;
418
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, out->handle);
421}
422
423static void release_in_focus(struct stream_in *in)
424{
425 struct audio_device *adev = in->dev;
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
428}
429
vivek mehtaa76401a2015-04-24 14:12:15 -0700430__attribute__ ((visibility ("default")))
431bool audio_hw_send_gain_dep_calibration(int level) {
432 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700433 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700434
435 pthread_mutex_lock(&adev_init_lock);
436
437 if (adev != NULL && adev->platform != NULL) {
438 pthread_mutex_lock(&adev->lock);
439 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700440
441 // if cal set fails, cache level info
442 // if cal set succeds, reset known last cal set
443 if (!ret_val)
444 last_known_cal_step = level;
445 else if (last_known_cal_step != -1)
446 last_known_cal_step = -1;
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448 pthread_mutex_unlock(&adev->lock);
449 } else {
450 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
451 }
452
453 pthread_mutex_unlock(&adev_init_lock);
454
455 return ret_val;
456}
457
Ashish Jain5106d362016-05-11 19:23:33 +0530458static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
459{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800460 bool gapless_enabled = false;
461 const char *mixer_ctl_name = "Compress Gapless Playback";
462 struct mixer_ctl *ctl;
463
464 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530465 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
466
467 /*Disable gapless if its AV playback*/
468 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800469
470 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
471 if (!ctl) {
472 ALOGE("%s: Could not get ctl for mixer cmd - %s",
473 __func__, mixer_ctl_name);
474 return -EINVAL;
475 }
476
477 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
478 ALOGE("%s: Could not set gapless mode %d",
479 __func__, gapless_enabled);
480 return -EINVAL;
481 }
482 return 0;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent86e17132013-09-12 17:49:30 -0700487 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530488 format == AUDIO_FORMAT_AAC_LC ||
489 format == AUDIO_FORMAT_AAC_HE_V1 ||
490 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530491 format == AUDIO_FORMAT_AAC_ADTS_LC ||
492 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
493 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530494 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
495 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530496 format == AUDIO_FORMAT_PCM_FLOAT ||
497 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700498 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530499 format == AUDIO_FORMAT_AC3 ||
500 format == AUDIO_FORMAT_E_AC3 ||
501 format == AUDIO_FORMAT_DTS ||
502 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800503 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530504 format == AUDIO_FORMAT_ALAC ||
505 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530506 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530507 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800508 format == AUDIO_FORMAT_WMA ||
509 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800510 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700511
512 return false;
513}
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static inline bool is_mmap_usecase(audio_usecase_t uc_id)
516{
517 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
518 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static int get_snd_codec_id(audio_format_t format)
522{
523 int id = 0;
524
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526 case AUDIO_FORMAT_MP3:
527 id = SND_AUDIOCODEC_MP3;
528 break;
529 case AUDIO_FORMAT_AAC:
530 id = SND_AUDIOCODEC_AAC;
531 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530532 case AUDIO_FORMAT_AAC_ADTS:
533 id = SND_AUDIOCODEC_AAC;
534 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700535 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800536 id = SND_AUDIOCODEC_PCM;
537 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700538 case AUDIO_FORMAT_FLAC:
539 id = SND_AUDIOCODEC_FLAC;
540 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530541 case AUDIO_FORMAT_ALAC:
542 id = SND_AUDIOCODEC_ALAC;
543 break;
544 case AUDIO_FORMAT_APE:
545 id = SND_AUDIOCODEC_APE;
546 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 case AUDIO_FORMAT_DSD:
548 id = SND_AUDIOCODEC_DSD;
549 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530550 case AUDIO_FORMAT_VORBIS:
551 id = SND_AUDIOCODEC_VORBIS;
552 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800553 case AUDIO_FORMAT_WMA:
554 id = SND_AUDIOCODEC_WMA;
555 break;
556 case AUDIO_FORMAT_WMA_PRO:
557 id = SND_AUDIOCODEC_WMA_PRO;
558 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530559 case AUDIO_FORMAT_AC3:
560 id = SND_AUDIOCODEC_AC3;
561 break;
562 case AUDIO_FORMAT_E_AC3:
563 case AUDIO_FORMAT_E_AC3_JOC:
564 id = SND_AUDIOCODEC_EAC3;
565 break;
566 case AUDIO_FORMAT_DTS:
567 case AUDIO_FORMAT_DTS_HD:
568 id = SND_AUDIOCODEC_DTS;
569 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700570 default:
Mingming Yin90310102013-11-13 16:57:00 -0800571 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 }
573
574 return id;
575}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800576
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530577int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530578{
579 int snd_scard_state;
580
581 if (!adev)
582 return SND_CARD_STATE_OFFLINE;
583
584 pthread_mutex_lock(&adev->snd_card_status.lock);
585 snd_scard_state = adev->snd_card_status.state;
586 pthread_mutex_unlock(&adev->snd_card_status.lock);
587
588 return snd_scard_state;
589}
590
591static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
592{
593 if (!adev)
594 return -ENOSYS;
595
596 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700597 if (adev->snd_card_status.state != snd_scard_state) {
598 adev->snd_card_status.state = snd_scard_state;
599 platform_snd_card_update(adev->platform, snd_scard_state);
600 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530601 pthread_mutex_unlock(&adev->snd_card_status.lock);
602
603 return 0;
604}
605
Avinash Vaish71a8b972014-07-24 15:36:33 +0530606static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
607 struct audio_usecase *uc_info)
608{
609 struct listnode *node;
610 struct audio_usecase *usecase;
611
612 if (uc_info == NULL)
613 return -EINVAL;
614
615 /* Re-route all voice usecases on the shared backend other than the
616 specified usecase to new snd devices */
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800619 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530620 enable_audio_route(adev, usecase);
621 }
622 return 0;
623}
624
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530625static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530626{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530627 ALOGV("%s", __func__);
628 audio_route_apply_and_update_path(adev->audio_route,
629 "asrc-mode");
630 adev->asrc_mode_enabled = true;
631}
632
633static void disable_asrc_mode(struct audio_device *adev)
634{
635 ALOGV("%s", __func__);
636 audio_route_reset_and_update_path(adev->audio_route,
637 "asrc-mode");
638 adev->asrc_mode_enabled = false;
639}
640
641/*
642 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
643 * 44.1 or Native DSD backends are enabled for any of current use case.
644 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
645 * - Disable current mix path use case(Headphone backend) and re-enable it with
646 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
647 * e.g. Naitve DSD or Headphone 44.1 -> + 48
648 */
649static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
650{
651 ALOGV("%s snd device %d", __func__, snd_device);
652 int new_backend_idx = platform_get_backend_index(snd_device);
653
654 if (((new_backend_idx == HEADPHONE_BACKEND) ||
655 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
656 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
657 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530658 struct listnode *node = NULL;
659 struct audio_usecase *uc = NULL;
660 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530662
663 list_for_each(node, &adev->usecase_list) {
664 uc = node_to_item(node, struct audio_usecase, list);
665 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530666 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530667 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
668
669 if((new_backend_idx == HEADPHONE_BACKEND) &&
670 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
671 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530672 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
673 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530674 enable_asrc_mode(adev);
675 break;
676 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
677 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
678 (usecase_backend_idx == HEADPHONE_BACKEND)) {
679 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
680 __func__);
681 disable_audio_route(adev, uc);
682 disable_snd_device(adev, uc->out_snd_device);
683 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
684 if (new_backend_idx == DSD_NATIVE_BACKEND)
685 audio_route_apply_and_update_path(adev->audio_route,
686 "hph-true-highquality-mode");
687 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
688 (curr_out->bit_width >= 24))
689 audio_route_apply_and_update_path(adev->audio_route,
690 "hph-highquality-mode");
691 enable_asrc_mode(adev);
692 enable_snd_device(adev, uc->out_snd_device);
693 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530694 break;
695 }
696 }
697 }
698 }
699}
700
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700701int pcm_ioctl(struct pcm *pcm, int request, ...)
702{
703 va_list ap;
704 void * arg;
705 int pcm_fd = *(int*)pcm;
706
707 va_start(ap, request);
708 arg = va_arg(ap, void *);
709 va_end(ap);
710
711 return ioctl(pcm_fd, request, arg);
712}
713
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700714int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700715 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800716{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700718 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800719
720 if (usecase == NULL)
721 return -EINVAL;
722
723 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
724
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800725 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800727 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800729
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800730#ifdef DS1_DOLBY_DAP_ENABLED
731 audio_extn_dolby_set_dmid(adev);
732 audio_extn_dolby_set_endpoint(adev);
733#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700734 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700735 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530736 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700737 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530738 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800739 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700740 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700741 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700742 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743 ALOGV("%s: exit", __func__);
744 return 0;
745}
746
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700747int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700748 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700751 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800752
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530753 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800754 return -EINVAL;
755
756 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700757 if (usecase->type == PCM_CAPTURE)
758 snd_device = usecase->in_snd_device;
759 else
760 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800761 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700762 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700763 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700764 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700765 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530766 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767 ALOGV("%s: exit", __func__);
768 return 0;
769}
770
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700771int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700772 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530774 int i, num_devices = 0;
775 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700776 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
777
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800778 if (snd_device < SND_DEVICE_MIN ||
779 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800780 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800781 return -EINVAL;
782 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700783
784 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700785
786 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
787 ALOGE("%s: Invalid sound device returned", __func__);
788 return -EINVAL;
789 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700791 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700792 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700793 return 0;
794 }
795
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530796
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700797 if (audio_extn_spkr_prot_is_enabled())
798 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700799
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800800 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
801 audio_extn_spkr_prot_is_enabled()) {
802 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700803 adev->snd_dev_ref_cnt[snd_device]--;
804 return -EINVAL;
805 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200806 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800807 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800808 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200809 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800810 return -EINVAL;
811 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530812 } else if (platform_can_split_snd_device(adev->platform, snd_device,
813 &num_devices, new_snd_devices)) {
814 for (i = 0; i < num_devices; i++) {
815 enable_snd_device(adev, new_snd_devices[i]);
816 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800817 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700818 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530819
820 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
821 (audio_extn_a2dp_start_playback() < 0)) {
822 ALOGE(" fail to configure A2dp control path ");
823 return -EINVAL;
824 }
825
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700826 /* due to the possibility of calibration overwrite between listen
827 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700828 audio_extn_sound_trigger_update_device_status(snd_device,
829 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530830 audio_extn_listen_update_device_status(snd_device,
831 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700832 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700833 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700834 audio_extn_sound_trigger_update_device_status(snd_device,
835 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530836 audio_extn_listen_update_device_status(snd_device,
837 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700838 return -EINVAL;
839 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300840 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700841 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530842
843 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
844 !adev->native_playback_enabled &&
845 audio_is_true_native_stream_active(adev)) {
846 ALOGD("%s: %d: napb: enabling native mode in hardware",
847 __func__, __LINE__);
848 audio_route_apply_and_update_path(adev->audio_route,
849 "true-native-mode");
850 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853 return 0;
854}
855
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700856int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700857 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800858{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530859 int i, num_devices = 0;
860 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700861 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
862
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800863 if (snd_device < SND_DEVICE_MIN ||
864 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800865 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800866 return -EINVAL;
867 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
869 ALOGE("%s: device ref cnt is already 0", __func__);
870 return -EINVAL;
871 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700872
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700874
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
876 ALOGE("%s: Invalid sound device returned", __func__);
877 return -EINVAL;
878 }
879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700881 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530882
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800883 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
884 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700885 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530886 } else if (platform_can_split_snd_device(adev->platform, snd_device,
887 &num_devices, new_snd_devices)) {
888 for (i = 0; i < num_devices; i++) {
889 disable_snd_device(adev, new_snd_devices[i]);
890 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300891 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700892 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300893 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700894
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530895 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
896 audio_extn_a2dp_stop_playback();
897
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700898 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530899 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530900 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
901 adev->native_playback_enabled) {
902 ALOGD("%s: %d: napb: disabling native mode in hardware",
903 __func__, __LINE__);
904 audio_route_reset_and_update_path(adev->audio_route,
905 "true-native-mode");
906 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530907 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
908 adev->asrc_mode_enabled) {
909 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530910 disable_asrc_mode(adev);
911 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530912 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530913
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200914 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700915 audio_extn_sound_trigger_update_device_status(snd_device,
916 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530917 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800918 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800921 return 0;
922}
923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700924static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530925 struct audio_usecase *uc_info,
926 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927{
928 struct listnode *node;
929 struct audio_usecase *usecase;
930 bool switch_device[AUDIO_USECASE_MAX];
931 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530932 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 /*
934 * This function is to make sure that all the usecases that are active on
935 * the hardware codec backend are always routed to any one device that is
936 * handled by the hardware codec.
937 * For example, if low-latency and deep-buffer usecases are currently active
938 * on speaker and out_set_parameters(headset) is received on low-latency
939 * output, then we have to make sure deep-buffer is also switched to headset,
940 * because of the limitation that both the devices cannot be enabled
941 * at the same time as they share the same backend.
942 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700943 /*
944 * This call is to check if we need to force routing for a particular stream
945 * If there is a backend configuration change for the device when a
946 * new stream starts, then ADM needs to be closed and re-opened with the new
947 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800948 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700949 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800950 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
951 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530952 /* For a2dp device reconfigure all active sessions
953 * with new AFE encoder format based on a2dp state
954 */
955 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
956 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
957 audio_extn_a2dp_is_force_device_switch()) {
958 force_routing = true;
959 force_restart_session = true;
960 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530961 ALOGD("%s:becf: force routing %d", __func__, force_routing);
962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800964 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800965 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 for (i = 0; i < AUDIO_USECASE_MAX; i++)
967 switch_device[i] = false;
968
969 list_for_each(node, &adev->usecase_list) {
970 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800971
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530972 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
973 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530974 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530975 platform_get_snd_device_name(usecase->out_snd_device),
976 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800977 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530978 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530979 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530980 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
981 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530982 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530983 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530984 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
985
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530986 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
987 __func__, use_case_table[usecase->id],
988 platform_get_snd_device_name(usecase->out_snd_device));
989 disable_audio_route(adev, usecase);
990 switch_device[usecase->id] = true;
991 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700992 }
993 }
994
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530995 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
996 num_uc_to_switch);
997
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700999 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301001 /* Make sure the previous devices to be disabled first and then enable the
1002 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001006 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001007 }
1008 }
1009
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001010 list_for_each(node, &adev->usecase_list) {
1011 usecase = node_to_item(node, struct audio_usecase, list);
1012 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001013 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001014 }
1015 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 /* Re-route all the usecases on the shared backend other than the
1018 specified usecase to new snd devices */
1019 list_for_each(node, &adev->usecase_list) {
1020 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301021 /* Update the out_snd_device only before enabling the audio route */
1022 if (switch_device[usecase->id]) {
1023 usecase->out_snd_device = snd_device;
1024 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301025 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301026 use_case_table[usecase->id],
1027 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301028 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301029 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 }
1031 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 }
1033}
1034
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301035static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 struct audio_usecase *uc_info,
1037 snd_device_t snd_device)
1038{
1039 struct listnode *node;
1040 struct audio_usecase *usecase;
1041 bool switch_device[AUDIO_USECASE_MAX];
1042 int i, num_uc_to_switch = 0;
1043
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301044 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1045 snd_device);
1046 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001047 /*
1048 * This function is to make sure that all the active capture usecases
1049 * are always routed to the same input sound device.
1050 * For example, if audio-record and voice-call usecases are currently
1051 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1052 * is received for voice call then we have to make sure that audio-record
1053 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1054 * because of the limitation that two devices cannot be enabled
1055 * at the same time if they share the same backend.
1056 */
1057 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1058 switch_device[i] = false;
1059
1060 list_for_each(node, &adev->usecase_list) {
1061 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001062 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001063 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301064 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001065 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301066 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001067 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001068 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001069 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1070 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001071 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001072 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001073 switch_device[usecase->id] = true;
1074 num_uc_to_switch++;
1075 }
1076 }
1077
1078 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001079 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001080
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301081 /* Make sure the previous devices to be disabled first and then enable the
1082 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001083 list_for_each(node, &adev->usecase_list) {
1084 usecase = node_to_item(node, struct audio_usecase, list);
1085 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001087 }
1088 }
1089
1090 list_for_each(node, &adev->usecase_list) {
1091 usecase = node_to_item(node, struct audio_usecase, list);
1092 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001093 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001094 }
1095 }
1096
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001097 /* Re-route all the usecases on the shared backend other than the
1098 specified usecase to new snd devices */
1099 list_for_each(node, &adev->usecase_list) {
1100 usecase = node_to_item(node, struct audio_usecase, list);
1101 /* Update the in_snd_device only before enabling the audio route */
1102 if (switch_device[usecase->id] ) {
1103 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001104 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301105 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001106 }
1107 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001108 }
1109}
1110
Mingming Yin3a941d42016-02-17 18:08:05 -08001111static void reset_hdmi_sink_caps(struct stream_out *out) {
1112 int i = 0;
1113
1114 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1115 out->supported_channel_masks[i] = 0;
1116 }
1117 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1118 out->supported_formats[i] = 0;
1119 }
1120 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1121 out->supported_sample_rates[i] = 0;
1122 }
1123}
1124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001126static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127{
Mingming Yin3a941d42016-02-17 18:08:05 -08001128 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001129 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130
Mingming Yin3a941d42016-02-17 18:08:05 -08001131 reset_hdmi_sink_caps(out);
1132
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001133 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001134 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001135 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001136 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001137 }
1138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001141 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001142 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001143 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1144 case 6:
1145 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1146 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1147 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1148 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1149 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1150 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151 break;
1152 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001153 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001154 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 break;
1156 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001157
1158 // check channel format caps
1159 i = 0;
1160 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1161 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1162 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1163 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1164 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1165 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1166 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1167 }
1168
1169 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1170 ALOGV(":%s HDMI supports DTS format", __func__);
1171 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1172 }
1173
1174 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1175 ALOGV(":%s HDMI supports DTS HD format", __func__);
1176 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1177 }
1178
1179
1180 // check sample rate caps
1181 i = 0;
1182 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1183 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1184 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1185 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1186 }
1187 }
1188
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001189 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001190}
1191
Alexy Josephb1379942016-01-29 15:49:38 -08001192audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001193 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001194{
1195 struct audio_usecase *usecase;
1196 struct listnode *node;
1197
1198 list_for_each(node, &adev->usecase_list) {
1199 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001200 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001201 ALOGV("%s: usecase id %d", __func__, usecase->id);
1202 return usecase->id;
1203 }
1204 }
1205 return USECASE_INVALID;
1206}
1207
Alexy Josephb1379942016-01-29 15:49:38 -08001208struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001209 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210{
1211 struct audio_usecase *usecase;
1212 struct listnode *node;
1213
1214 list_for_each(node, &adev->usecase_list) {
1215 usecase = node_to_item(node, struct audio_usecase, list);
1216 if (usecase->id == uc_id)
1217 return usecase;
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) &&
1306 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1307 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)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001337 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001338 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001339 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 usecase->devices = usecase->stream.out->devices;
1341 } else {
1342 /*
1343 * If the voice call is active, use the sound devices of voice call usecase
1344 * so that it would not result any device switch. All the usecases will
1345 * be switched to new device when select_devices() is called for voice call
1346 * usecase. This is to avoid switching devices for voice call when
1347 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001348 * choose voice call device only if the use case device is
1349 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001351 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001352 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001353 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001354 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1355 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301356 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1357 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001358 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 in_snd_device = vc_usecase->in_snd_device;
1360 out_snd_device = vc_usecase->out_snd_device;
1361 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001362 } else if (voice_extn_compress_voip_is_active(adev)) {
1363 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001364 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001365 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1366 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001367 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001368 in_snd_device = voip_usecase->in_snd_device;
1369 out_snd_device = voip_usecase->out_snd_device;
1370 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001371 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001372 hfp_ucid = audio_extn_hfp_get_usecase();
1373 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001374 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001375 in_snd_device = hfp_usecase->in_snd_device;
1376 out_snd_device = hfp_usecase->out_snd_device;
1377 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 }
1379 if (usecase->type == PCM_PLAYBACK) {
1380 usecase->devices = usecase->stream.out->devices;
1381 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001382 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001383 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001384 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001385 if (usecase->stream.out == adev->primary_output &&
1386 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001387 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001388 select_devices(adev, adev->active_input->usecase);
1389 }
1390 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 } else if (usecase->type == PCM_CAPTURE) {
1392 usecase->devices = usecase->stream.in->device;
1393 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001394 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001395 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001396 if (adev->active_input &&
1397 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301398 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1399 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1400 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001401 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001402 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001403 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1404 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001405 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001406 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001407 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 }
1409 }
1410
1411 if (out_snd_device == usecase->out_snd_device &&
1412 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301413
1414 if (!force_device_switch(usecase))
1415 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 }
1417
sangwoobc677242013-08-08 16:53:43 +09001418 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001419 out_snd_device, platform_get_snd_device_name(out_snd_device),
1420 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 /*
1423 * Limitation: While in call, to do a device switch we need to disable
1424 * and enable both RX and TX devices though one of them is same as current
1425 * device.
1426 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001427 if ((usecase->type == VOICE_CALL) &&
1428 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1429 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001430 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001431 }
1432
1433 if (((usecase->type == VOICE_CALL) ||
1434 (usecase->type == VOIP_CALL)) &&
1435 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1436 /* Disable sidetone only if voice/voip call already exists */
1437 if (voice_is_call_state_active(adev) ||
1438 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001439 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001440 }
1441
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442 /* Disable current sound devices */
1443 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001444 disable_audio_route(adev, usecase);
1445 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446 }
1447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001449 disable_audio_route(adev, usecase);
1450 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 }
1452
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001453 /* Applicable only on the targets that has external modem.
1454 * New device information should be sent to modem before enabling
1455 * the devices to reduce in-call device switch time.
1456 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001457 if ((usecase->type == VOICE_CALL) &&
1458 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1459 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001460 status = platform_switch_voice_call_enable_device_config(adev->platform,
1461 out_snd_device,
1462 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001463 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001464
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465 /* Enable new sound devices */
1466 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001467 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301468 if (platform_check_codec_asrc_support(adev->platform))
1469 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001470 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471 }
1472
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001473 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301474 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001475 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001476 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477
Avinash Vaish71a8b972014-07-24 15:36:33 +05301478 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001479 status = platform_switch_voice_call_device_post(adev->platform,
1480 out_snd_device,
1481 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301482 enable_audio_route_for_voice_usecases(adev, usecase);
1483 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001484
sangwoo170731f2013-06-08 15:36:36 +09001485 usecase->in_snd_device = in_snd_device;
1486 usecase->out_snd_device = out_snd_device;
1487
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301488 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001489 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301490 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001491 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301492 usecase->stream.out->flags,
1493 usecase->stream.out->format,
1494 usecase->stream.out->sample_rate,
1495 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301496 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301497 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001498 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001499
1500 /* Notify device change info to effect clients registered */
1501 audio_extn_gef_notify_device_config(
1502 usecase->stream.out->devices,
1503 usecase->stream.out->channel_mask,
1504 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301505 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001506
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001507 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001508
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001509 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1510 /* Enable sidetone only if other voice/voip call already exists */
1511 if (voice_is_call_state_active(adev) ||
1512 voice_extn_compress_voip_is_started(adev))
1513 voice_set_sidetone(adev, out_snd_device, true);
1514 }
1515
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001516 /* Applicable only on the targets that has external modem.
1517 * Enable device command should be sent to modem only after
1518 * enabling voice call mixer controls
1519 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001520 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001521 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1522 out_snd_device,
1523 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301524 ALOGD("%s: done",__func__);
1525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 return status;
1527}
1528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529static int stop_input_stream(struct stream_in *in)
1530{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301531 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 struct audio_usecase *uc_info;
1533 struct audio_device *adev = in->dev;
1534
Eric Laurentc8400632013-02-14 19:04:54 -08001535 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536
Eric Laurent994a6932013-07-17 11:51:42 -07001537 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 uc_info = get_usecase_from_list(adev, in->usecase);
1540 if (uc_info == NULL) {
1541 ALOGE("%s: Could not find the usecase (%d) in the list",
1542 __func__, in->usecase);
1543 return -EINVAL;
1544 }
1545
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001546 /* Close in-call recording streams */
1547 voice_check_and_stop_incall_rec_usecase(adev, in);
1548
Eric Laurent150dbfe2013-02-27 14:31:02 -08001549 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001550 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001551
1552 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001553 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001555 list_remove(&uc_info->list);
1556 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557
Eric Laurent994a6932013-07-17 11:51:42 -07001558 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 return ret;
1560}
1561
1562int start_input_stream(struct stream_in *in)
1563{
1564 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001565 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 struct audio_usecase *uc_info;
1567 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301568 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569
Mingming Yin2664a5b2015-09-03 10:53:11 -07001570 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1571 if (get_usecase_from_list(adev, usecase) == NULL)
1572 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301573 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1574 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001575
Naresh Tanniru80659832014-06-04 18:17:56 +05301576
1577 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301578 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301579 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301580 goto error_config;
1581 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301582
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001583 /* Check if source matches incall recording usecase criteria */
1584 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1585 if (ret)
1586 goto error_config;
1587 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001588 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1589
1590 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1591 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1592 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001593 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001594 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001595
Eric Laurentb23d5282013-05-14 15:27:20 -07001596 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 if (in->pcm_device_id < 0) {
1598 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1599 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001600 ret = -EINVAL;
1601 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603
1604 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001606
1607 if (!uc_info) {
1608 ret = -ENOMEM;
1609 goto error_config;
1610 }
1611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 uc_info->id = in->usecase;
1613 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001614 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001615 uc_info->devices = in->device;
1616 uc_info->in_snd_device = SND_DEVICE_NONE;
1617 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001619 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301620 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1621 adev->perf_lock_opts,
1622 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001623 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301625 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1626 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001627
1628 unsigned int flags = PCM_IN;
1629 unsigned int pcm_open_retry_count = 0;
1630
1631 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1632 flags |= PCM_MMAP | PCM_NOIRQ;
1633 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001634 } else if (in->realtime) {
1635 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001636 }
1637
1638 while (1) {
1639 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1640 flags, &in->config);
1641 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1642 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1643 if (in->pcm != NULL) {
1644 pcm_close(in->pcm);
1645 in->pcm = NULL;
1646 }
1647 if (pcm_open_retry_count-- == 0) {
1648 ret = -EIO;
1649 goto error_open;
1650 }
1651 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1652 continue;
1653 }
1654 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001656
1657 ALOGV("%s: pcm_prepare", __func__);
1658 ret = pcm_prepare(in->pcm);
1659 if (ret < 0) {
1660 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1661 pcm_close(in->pcm);
1662 in->pcm = NULL;
1663 goto error_open;
1664 }
1665
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001666 register_in_stream(in);
1667 if (in->realtime) {
1668 ret = pcm_start(in->pcm);
1669 if (ret < 0)
1670 goto error_open;
1671 }
1672
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301673 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001674 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001675
Eric Laurentc8400632013-02-14 19:04:54 -08001676 return ret;
1677
1678error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301679 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001681error_config:
1682 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301683 /*
1684 * sleep 50ms to allow sufficient time for kernel
1685 * drivers to recover incases like SSR.
1686 */
1687 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001688 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001689
1690 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691}
1692
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001693void lock_input_stream(struct stream_in *in)
1694{
1695 pthread_mutex_lock(&in->pre_lock);
1696 pthread_mutex_lock(&in->lock);
1697 pthread_mutex_unlock(&in->pre_lock);
1698}
1699
1700void lock_output_stream(struct stream_out *out)
1701{
1702 pthread_mutex_lock(&out->pre_lock);
1703 pthread_mutex_lock(&out->lock);
1704 pthread_mutex_unlock(&out->pre_lock);
1705}
1706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707/* must be called with out->lock locked */
1708static int send_offload_cmd_l(struct stream_out* out, int command)
1709{
1710 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1711
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001712 if (!cmd) {
1713 ALOGE("failed to allocate mem for command 0x%x", command);
1714 return -ENOMEM;
1715 }
1716
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717 ALOGVV("%s %d", __func__, command);
1718
1719 cmd->cmd = command;
1720 list_add_tail(&out->offload_cmd_list, &cmd->node);
1721 pthread_cond_signal(&out->offload_cond);
1722 return 0;
1723}
1724
1725/* must be called iwth out->lock locked */
1726static void stop_compressed_output_l(struct stream_out *out)
1727{
1728 out->offload_state = OFFLOAD_STATE_IDLE;
1729 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001730 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 if (out->compr != NULL) {
1732 compress_stop(out->compr);
1733 while (out->offload_thread_blocked) {
1734 pthread_cond_wait(&out->cond, &out->lock);
1735 }
1736 }
1737}
1738
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001739bool is_offload_usecase(audio_usecase_t uc_id)
1740{
1741 unsigned int i;
1742 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1743 if (uc_id == offload_usecases[i])
1744 return true;
1745 }
1746 return false;
1747}
1748
vivek mehta446c3962015-09-14 10:57:35 -07001749static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001750{
vivek mehta446c3962015-09-14 10:57:35 -07001751 audio_usecase_t ret_uc = USECASE_INVALID;
1752 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001753 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001754 if (!adev->multi_offload_enable) {
1755 if (is_direct_pcm)
1756 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1757 else
1758 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001759
vivek mehta446c3962015-09-14 10:57:35 -07001760 pthread_mutex_lock(&adev->lock);
1761 if (get_usecase_from_list(adev, ret_uc) != NULL)
1762 ret_uc = USECASE_INVALID;
1763 pthread_mutex_unlock(&adev->lock);
1764
1765 return ret_uc;
1766 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001767
1768 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001769 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1770 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1771 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1772 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001773 break;
1774 }
1775 }
vivek mehta446c3962015-09-14 10:57:35 -07001776
1777 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1778 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001779}
1780
1781static void free_offload_usecase(struct audio_device *adev,
1782 audio_usecase_t uc_id)
1783{
vivek mehta446c3962015-09-14 10:57:35 -07001784 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001785 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001786
1787 if (!adev->multi_offload_enable)
1788 return;
1789
1790 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1791 if (offload_usecases[offload_uc_index] == uc_id) {
1792 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001793 break;
1794 }
1795 }
1796 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1797}
1798
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799static void *offload_thread_loop(void *context)
1800{
1801 struct stream_out *out = (struct stream_out *) context;
1802 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001803 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1806 set_sched_policy(0, SP_FOREGROUND);
1807 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1808
1809 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001810 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001811 for (;;) {
1812 struct offload_cmd *cmd = NULL;
1813 stream_callback_event_t event;
1814 bool send_callback = false;
1815
1816 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1817 __func__, list_empty(&out->offload_cmd_list),
1818 out->offload_state);
1819 if (list_empty(&out->offload_cmd_list)) {
1820 ALOGV("%s SLEEPING", __func__);
1821 pthread_cond_wait(&out->offload_cond, &out->lock);
1822 ALOGV("%s RUNNING", __func__);
1823 continue;
1824 }
1825
1826 item = list_head(&out->offload_cmd_list);
1827 cmd = node_to_item(item, struct offload_cmd, node);
1828 list_remove(item);
1829
1830 ALOGVV("%s STATE %d CMD %d out->compr %p",
1831 __func__, out->offload_state, cmd->cmd, out->compr);
1832
1833 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1834 free(cmd);
1835 break;
1836 }
1837
1838 if (out->compr == NULL) {
1839 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001840 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001841 pthread_cond_signal(&out->cond);
1842 continue;
1843 }
1844 out->offload_thread_blocked = true;
1845 pthread_mutex_unlock(&out->lock);
1846 send_callback = false;
1847 switch(cmd->cmd) {
1848 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001849 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001851 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001852 send_callback = true;
1853 event = STREAM_CBK_EVENT_WRITE_READY;
1854 break;
1855 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001856 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301857 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001858 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301859 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001860 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301861 if (ret < 0)
1862 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301863 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301864 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001865 compress_drain(out->compr);
1866 else
1867 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301868 if (ret != -ENETRESET) {
1869 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301870 pthread_mutex_lock(&out->lock);
1871 out->send_new_metadata = 1;
1872 out->send_next_track_params = true;
1873 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301874 event = STREAM_CBK_EVENT_DRAIN_READY;
1875 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1876 } else
1877 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 break;
1879 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001880 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001881 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001882 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001883 send_callback = true;
1884 event = STREAM_CBK_EVENT_DRAIN_READY;
1885 break;
1886 default:
1887 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1888 break;
1889 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001890 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001891 out->offload_thread_blocked = false;
1892 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001893 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001894 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001895 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001896 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001897 free(cmd);
1898 }
1899
1900 pthread_cond_signal(&out->cond);
1901 while (!list_empty(&out->offload_cmd_list)) {
1902 item = list_head(&out->offload_cmd_list);
1903 list_remove(item);
1904 free(node_to_item(item, struct offload_cmd, node));
1905 }
1906 pthread_mutex_unlock(&out->lock);
1907
1908 return NULL;
1909}
1910
1911static int create_offload_callback_thread(struct stream_out *out)
1912{
1913 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1914 list_init(&out->offload_cmd_list);
1915 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1916 offload_thread_loop, out);
1917 return 0;
1918}
1919
1920static int destroy_offload_callback_thread(struct stream_out *out)
1921{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001922 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001923 stop_compressed_output_l(out);
1924 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1925
1926 pthread_mutex_unlock(&out->lock);
1927 pthread_join(out->offload_thread, (void **) NULL);
1928 pthread_cond_destroy(&out->offload_cond);
1929
1930 return 0;
1931}
1932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933static int stop_output_stream(struct stream_out *out)
1934{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301935 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 struct audio_usecase *uc_info;
1937 struct audio_device *adev = out->dev;
1938
Eric Laurent994a6932013-07-17 11:51:42 -07001939 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 uc_info = get_usecase_from_list(adev, out->usecase);
1942 if (uc_info == NULL) {
1943 ALOGE("%s: Could not find the usecase (%d) in the list",
1944 __func__, out->usecase);
1945 return -EINVAL;
1946 }
1947
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001948 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301949 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001950 if (adev->visualizer_stop_output != NULL)
1951 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001952
1953 audio_extn_dts_remove_state_notifier_node(out->usecase);
1954
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001955 if (adev->offload_effects_stop_output != NULL)
1956 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1957 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001958
Eric Laurent150dbfe2013-02-27 14:31:02 -08001959 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001960 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001961
1962 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001963 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001965 list_remove(&uc_info->list);
1966 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967
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))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001970 ALOGV("Disable passthrough , reset mixer to pcm");
1971 /* NO_PASSTHROUGH */
1972 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001973 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001974 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1975 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001976
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301977 /* Must be called after removing the usecase from list */
1978 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301979 audio_extn_keep_alive_start();
1980
Eric Laurent994a6932013-07-17 11:51:42 -07001981 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 return ret;
1983}
1984
1985int start_output_stream(struct stream_out *out)
1986{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 struct audio_usecase *uc_info;
1989 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301990 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001992 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1993 ret = -EINVAL;
1994 goto error_config;
1995 }
1996
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301997 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1998 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1999 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302000
Naresh Tanniru80659832014-06-04 18:17:56 +05302001 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302002 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302003 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302004 goto error_config;
2005 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302006
Eric Laurentb23d5282013-05-14 15:27:20 -07002007 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 if (out->pcm_device_id < 0) {
2009 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2010 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002011 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002012 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 }
2014
2015 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002016
2017 if (!uc_info) {
2018 ret = -ENOMEM;
2019 goto error_config;
2020 }
2021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 uc_info->id = out->usecase;
2023 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002024 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002025 uc_info->devices = out->devices;
2026 uc_info->in_snd_device = SND_DEVICE_NONE;
2027 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002028 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302030 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2031 adev->perf_lock_opts,
2032 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302033
2034 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2035 audio_extn_keep_alive_stop();
2036 if (audio_extn_passthru_is_enabled() &&
2037 audio_extn_passthru_is_passthrough_stream(out)) {
2038 audio_extn_passthru_on_start(out);
2039 audio_extn_passthru_update_stream_configuration(adev, out);
2040 }
2041 }
2042
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002043 select_devices(adev, out->usecase);
2044
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002045 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2046 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002047 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002048 unsigned int flags = PCM_OUT;
2049 unsigned int pcm_open_retry_count = 0;
2050 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2051 flags |= PCM_MMAP | PCM_NOIRQ;
2052 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002053 } else if (out->realtime) {
2054 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002055 } else
2056 flags |= PCM_MONOTONIC;
2057
2058 while (1) {
2059 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2060 flags, &out->config);
2061 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2062 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2063 if (out->pcm != NULL) {
2064 pcm_close(out->pcm);
2065 out->pcm = NULL;
2066 }
2067 if (pcm_open_retry_count-- == 0) {
2068 ret = -EIO;
2069 goto error_open;
2070 }
2071 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2072 continue;
2073 }
2074 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002076
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002077 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2078 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002079
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002080 ALOGV("%s: pcm_prepare", __func__);
2081 if (pcm_is_ready(out->pcm)) {
2082 ret = pcm_prepare(out->pcm);
2083 if (ret < 0) {
2084 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2085 pcm_close(out->pcm);
2086 out->pcm = NULL;
2087 goto error_open;
2088 }
2089 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002091 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2092 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002094 out->compr = compress_open(adev->snd_card,
2095 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 COMPRESS_IN, &out->compr_config);
2097 if (out->compr && !is_compress_ready(out->compr)) {
2098 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2099 compress_close(out->compr);
2100 out->compr = NULL;
2101 ret = -EIO;
2102 goto error_open;
2103 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302104 /* compress_open sends params of the track, so reset the flag here */
2105 out->is_compr_metadata_avail = false;
2106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002107 if (out->offload_callback)
2108 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002109
Fred Oh3f43e742015-03-04 18:42:34 -08002110 /* Since small bufs uses blocking writes, a write will be blocked
2111 for the default max poll time (20s) in the event of an SSR.
2112 Reduce the poll time to observe and deal with SSR faster.
2113 */
Ashish Jain5106d362016-05-11 19:23:33 +05302114 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002115 compress_set_max_poll_wait(out->compr, 1000);
2116 }
2117
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002118 audio_extn_dts_create_state_notifier_node(out->usecase);
2119 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2120 popcount(out->channel_mask),
2121 out->playback_started);
2122
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002123#ifdef DS1_DOLBY_DDP_ENABLED
2124 if (audio_extn_is_dolby_format(out->format))
2125 audio_extn_dolby_send_ddp_endp_params(adev);
2126#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302127 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002128 if (adev->visualizer_start_output != NULL)
2129 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2130 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302131 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002132 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002135
2136 if (ret == 0) {
2137 register_out_stream(out);
2138 if (out->realtime) {
2139 ret = pcm_start(out->pcm);
2140 if (ret < 0)
2141 goto error_open;
2142 }
2143 }
2144
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302145 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002146 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002147
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002148 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302150 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002152error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302153 /*
2154 * sleep 50ms to allow sufficient time for kernel
2155 * drivers to recover incases like SSR.
2156 */
2157 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002158 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159}
2160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161static int check_input_parameters(uint32_t sample_rate,
2162 audio_format_t format,
2163 int channel_count)
2164{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002165 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302167 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2168 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2169 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002170 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302171 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002172
2173 switch (channel_count) {
2174 case 1:
2175 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302176 case 3:
2177 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002178 case 6:
2179 break;
2180 default:
2181 ret = -EINVAL;
2182 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183
2184 switch (sample_rate) {
2185 case 8000:
2186 case 11025:
2187 case 12000:
2188 case 16000:
2189 case 22050:
2190 case 24000:
2191 case 32000:
2192 case 44100:
2193 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302194 case 96000:
2195 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 break;
2197 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002198 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 }
2200
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002201 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202}
2203
2204static size_t get_input_buffer_size(uint32_t sample_rate,
2205 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002206 int channel_count,
2207 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208{
2209 size_t size = 0;
2210
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002211 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2212 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002214 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002215 if (is_low_latency)
2216 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302217
2218 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002220 /* make sure the size is multiple of 32 bytes
2221 * At 48 kHz mono 16-bit PCM:
2222 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2223 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2224 */
2225 size += 0x1f;
2226 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002227
2228 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
Ashish Jain058165c2016-09-28 23:18:48 +05302231static size_t get_output_period_size(uint32_t sample_rate,
2232 audio_format_t format,
2233 int channel_count,
2234 int duration /*in millisecs*/)
2235{
2236 size_t size = 0;
2237 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2238
2239 if ((duration == 0) || (sample_rate == 0) ||
2240 (bytes_per_sample == 0) || (channel_count == 0)) {
2241 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2242 bytes_per_sample, channel_count);
2243 return -EINVAL;
2244 }
2245
2246 size = (sample_rate *
2247 duration *
2248 bytes_per_sample *
2249 channel_count) / 1000;
2250 /*
2251 * To have same PCM samples for all channels, the buffer size requires to
2252 * be multiple of (number of channels * bytes per sample)
2253 * For writes to succeed, the buffer must be written at address which is multiple of 32
2254 */
2255 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2256
2257 return (size/(channel_count * bytes_per_sample));
2258}
2259
Ashish Jain5106d362016-05-11 19:23:33 +05302260static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2261{
2262 uint64_t actual_frames_rendered = 0;
2263 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2264
2265 /* This adjustment accounts for buffering after app processor.
2266 * It is based on estimated DSP latency per use case, rather than exact.
2267 */
2268 int64_t platform_latency = platform_render_latency(out->usecase) *
2269 out->sample_rate / 1000000LL;
2270
2271 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2272 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2273 * hence only estimate.
2274 */
2275 int64_t signed_frames = out->written - kernel_buffer_size;
2276
2277 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2278
2279 if (signed_frames > 0)
2280 actual_frames_rendered = signed_frames;
2281
2282 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2283 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2284 (long long int)out->written, (int)kernel_buffer_size,
2285 audio_bytes_per_sample(out->compr_config.codec->format),
2286 popcount(out->channel_mask));
2287
2288 return actual_frames_rendered;
2289}
2290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002295 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296}
2297
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002298static int out_set_sample_rate(struct audio_stream *stream __unused,
2299 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300{
2301 return -ENOSYS;
2302}
2303
2304static size_t out_get_buffer_size(const struct audio_stream *stream)
2305{
2306 struct stream_out *out = (struct stream_out *)stream;
2307
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002308 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002310 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2311 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302312 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302313 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002314
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002315 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002316 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317}
2318
2319static uint32_t out_get_channels(const struct audio_stream *stream)
2320{
2321 struct stream_out *out = (struct stream_out *)stream;
2322
2323 return out->channel_mask;
2324}
2325
2326static audio_format_t out_get_format(const struct audio_stream *stream)
2327{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002328 struct stream_out *out = (struct stream_out *)stream;
2329
2330 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331}
2332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002333static int out_set_format(struct audio_stream *stream __unused,
2334 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335{
2336 return -ENOSYS;
2337}
2338
2339static int out_standby(struct audio_stream *stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302344 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2345 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002347 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002349 if (adev->adm_deregister_stream)
2350 adev->adm_deregister_stream(adev->adm_data, out->handle);
2351
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002352 if (is_offload_usecase(out->usecase))
2353 stop_compressed_output_l(out);
2354
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002355 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002357 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2358 voice_extn_compress_voip_close_output_stream(stream);
2359 pthread_mutex_unlock(&adev->lock);
2360 pthread_mutex_unlock(&out->lock);
2361 ALOGD("VOIP output entered standby");
2362 return 0;
2363 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 if (out->pcm) {
2365 pcm_close(out->pcm);
2366 out->pcm = NULL;
2367 }
2368 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002369 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302370 out->send_next_track_params = false;
2371 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002372 out->gapless_mdata.encoder_delay = 0;
2373 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 if (out->compr != NULL) {
2375 compress_close(out->compr);
2376 out->compr = NULL;
2377 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002378 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002380 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 }
2382 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302383 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 return 0;
2385}
2386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002387static int out_dump(const struct audio_stream *stream __unused,
2388 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389{
2390 return 0;
2391}
2392
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002393static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2394{
2395 int ret = 0;
2396 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002397
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002398 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002399 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002400 return -EINVAL;
2401 }
2402
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302403 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002404
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002405 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2406 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302407 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002408 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002409 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2410 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302411 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002412 }
2413
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002414 ALOGV("%s new encoder delay %u and padding %u", __func__,
2415 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2416
2417 return 0;
2418}
2419
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002420static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2421{
2422 return out == adev->primary_output || out == adev->voice_tx_output;
2423}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2426{
2427 struct stream_out *out = (struct stream_out *)stream;
2428 struct audio_device *adev = out->dev;
2429 struct str_parms *parms;
2430 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002431 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432
sangwoobc677242013-08-08 16:53:43 +09002433 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002434 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302436 if (!parms)
2437 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002438 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2439 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002441 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002442 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002444 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002445 * When HDMI cable is unplugged the music playback is paused and
2446 * the policy manager sends routing=0. But the audioflinger continues
2447 * to write data until standby time (3sec). As the HDMI core is
2448 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002449 * Avoid this by routing audio to speaker until standby.
2450 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002451 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2452 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302453 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002454 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2455 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002456 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302457 /*
2458 * When A2DP is disconnected the
2459 * music playback is paused and the policy manager sends routing=0
2460 * But the audioflingercontinues to write data until standby time
2461 * (3sec). As BT is turned off, the write gets blocked.
2462 * Avoid this by routing audio to speaker until standby.
2463 */
2464 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2465 (val == AUDIO_DEVICE_NONE)) {
2466 val = AUDIO_DEVICE_OUT_SPEAKER;
2467 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002468
2469 /*
2470 * select_devices() call below switches all the usecases on the same
2471 * backend to the new device. Refer to check_usecases_codec_backend() in
2472 * the select_devices(). But how do we undo this?
2473 *
2474 * For example, music playback is active on headset (deep-buffer usecase)
2475 * and if we go to ringtones and select a ringtone, low-latency usecase
2476 * will be started on headset+speaker. As we can't enable headset+speaker
2477 * and headset devices at the same time, select_devices() switches the music
2478 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2479 * So when the ringtone playback is completed, how do we undo the same?
2480 *
2481 * We are relying on the out_set_parameters() call on deep-buffer output,
2482 * once the ringtone playback is ended.
2483 * NOTE: We should not check if the current devices are same as new devices.
2484 * Because select_devices() must be called to switch back the music
2485 * playback to headset.
2486 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002487 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002488 audio_devices_t new_dev = val;
2489 bool same_dev = out->devices == new_dev;
2490 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002491
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002492 if (output_drives_call(adev, out)) {
2493 if(!voice_is_in_call(adev)) {
2494 if (adev->mode == AUDIO_MODE_IN_CALL) {
2495 adev->current_call_output = out;
2496 ret = voice_start_call(adev);
2497 }
2498 } else {
2499 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002500 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002501 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002502 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002503
2504 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002505 if (!same_dev) {
2506 ALOGV("update routing change");
2507 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302508 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2509 adev->perf_lock_opts,
2510 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002511 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002512 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302513 if (!same_dev)
2514 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002515 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002516 }
2517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002521
2522 if (out == adev->primary_output) {
2523 pthread_mutex_lock(&adev->lock);
2524 audio_extn_set_parameters(adev, parms);
2525 pthread_mutex_unlock(&adev->lock);
2526 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002527 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002528 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002529 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002530
2531 audio_extn_dts_create_state_notifier_node(out->usecase);
2532 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2533 popcount(out->channel_mask),
2534 out->playback_started);
2535
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002536 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002537 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302540error:
Eric Laurent994a6932013-07-17 11:51:42 -07002541 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 return ret;
2543}
2544
2545static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2546{
2547 struct stream_out *out = (struct stream_out *)stream;
2548 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002549 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 char value[256];
2551 struct str_parms *reply = str_parms_create();
2552 size_t i, j;
2553 int ret;
2554 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002555
2556 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002557 if (reply) {
2558 str_parms_destroy(reply);
2559 }
2560 if (query) {
2561 str_parms_destroy(query);
2562 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002563 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2564 return NULL;
2565 }
2566
Eric Laurent994a6932013-07-17 11:51:42 -07002567 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2569 if (ret >= 0) {
2570 value[0] = '\0';
2571 i = 0;
2572 while (out->supported_channel_masks[i] != 0) {
2573 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2574 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2575 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002576 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002578 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 first = false;
2580 break;
2581 }
2582 }
2583 i++;
2584 }
2585 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2586 str = str_parms_to_str(reply);
2587 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002588 voice_extn_out_get_parameters(out, query, reply);
2589 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002590 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002591 free(str);
2592 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002595
Alexy Joseph62142aa2015-11-16 15:10:34 -08002596
2597 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2598 if (ret >= 0) {
2599 value[0] = '\0';
2600 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2601 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302602 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002603 } else {
2604 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302605 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002606 }
2607 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002608 if (str)
2609 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002610 str = str_parms_to_str(reply);
2611 }
2612
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002613 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2614 if (ret >= 0) {
2615 value[0] = '\0';
2616 i = 0;
2617 first = true;
2618 while (out->supported_formats[i] != 0) {
2619 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2620 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2621 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002622 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002623 }
2624 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2625 first = false;
2626 break;
2627 }
2628 }
2629 i++;
2630 }
2631 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002632 if (str)
2633 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002634 str = str_parms_to_str(reply);
2635 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002636
2637 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2638 if (ret >= 0) {
2639 value[0] = '\0';
2640 i = 0;
2641 first = true;
2642 while (out->supported_sample_rates[i] != 0) {
2643 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2644 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2645 if (!first) {
2646 strlcat(value, "|", sizeof(value));
2647 }
2648 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2649 first = false;
2650 break;
2651 }
2652 }
2653 i++;
2654 }
2655 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2656 if (str)
2657 free(str);
2658 str = str_parms_to_str(reply);
2659 }
2660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 str_parms_destroy(query);
2662 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002663 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 return str;
2665}
2666
2667static uint32_t out_get_latency(const struct audio_stream_out *stream)
2668{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002669 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002671 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672
Alexy Josephaa54c872014-12-03 02:46:47 -08002673 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002674 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002675 } else if (out->realtime) {
2676 // since the buffer won't be filled up faster than realtime,
2677 // return a smaller number
2678 if (out->config.rate)
2679 period_ms = (out->af_period_multiplier * out->config.period_size *
2680 1000) / (out->config.rate);
2681 else
2682 period_ms = 0;
2683 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002684 } else {
2685 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002686 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002687 }
2688
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302689 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002690 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691}
2692
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302693static float AmpToDb(float amplification)
2694{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302695 float db = DSD_VOLUME_MIN_DB;
2696 if (amplification > 0) {
2697 db = 20 * log10(amplification);
2698 if(db < DSD_VOLUME_MIN_DB)
2699 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302700 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302701 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302702}
2703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704static int out_set_volume(struct audio_stream_out *stream, float left,
2705 float right)
2706{
Eric Laurenta9024de2013-04-04 09:19:12 -07002707 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002708 int volume[2];
2709
Eric Laurenta9024de2013-04-04 09:19:12 -07002710 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2711 /* only take left channel into account: the API is for stereo anyway */
2712 out->muted = (left == 0.0f);
2713 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002714 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302715 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002716 /*
2717 * Set mute or umute on HDMI passthrough stream.
2718 * Only take left channel into account.
2719 * Mute is 0 and unmute 1
2720 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302721 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302722 } else if (out->format == AUDIO_FORMAT_DSD){
2723 char mixer_ctl_name[128] = "DSD Volume";
2724 struct audio_device *adev = out->dev;
2725 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2726
2727 if (!ctl) {
2728 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2729 __func__, mixer_ctl_name);
2730 return -EINVAL;
2731 }
2732 volume[0] = (int)(AmpToDb(left));
2733 volume[1] = (int)(AmpToDb(right));
2734 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2735 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002736 } else {
2737 char mixer_ctl_name[128];
2738 struct audio_device *adev = out->dev;
2739 struct mixer_ctl *ctl;
2740 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002741 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002742
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002743 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2744 "Compress Playback %d Volume", pcm_device_id);
2745 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2746 if (!ctl) {
2747 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2748 __func__, mixer_ctl_name);
2749 return -EINVAL;
2750 }
2751 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2752 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2753 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2754 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002755 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002756 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 return -ENOSYS;
2759}
2760
2761static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2762 size_t bytes)
2763{
2764 struct stream_out *out = (struct stream_out *)stream;
2765 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302766 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002767 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002769 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302770
Naresh Tanniru80659832014-06-04 18:17:56 +05302771 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002772
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302773 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302774 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302775 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2776 pthread_mutex_unlock(&out->lock);
2777 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302778 } else {
2779 /* increase written size during SSR to avoid mismatch
2780 * with the written frames count in AF
2781 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002782 // bytes per frame
2783 size_t bpf = audio_bytes_per_sample(out->format) *
2784 audio_channel_count_from_out_mask(out->channel_mask);
2785 if (bpf != 0)
2786 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302787 ALOGD(" %s: sound card is not active/SSR state", __func__);
2788 ret= -EIO;
2789 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302790 }
2791 }
2792
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302793 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302794 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2795 if (audio_bytes_per_sample(out->format) != 0)
2796 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2797 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302798 goto exit;
2799 }
2800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002802 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002803 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002804 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2805 ret = voice_extn_compress_voip_start_output_stream(out);
2806 else
2807 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002808 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002811 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 goto exit;
2813 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002814
2815 if (last_known_cal_step != -1) {
2816 ALOGD("%s: retry previous failed cal level set", __func__);
2817 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2818 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820
Ashish Jain81eb2a82015-05-13 10:52:34 +05302821 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002822 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302823 adev->is_channel_status_set = true;
2824 }
2825
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002826 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002827 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002828 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002829 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002830 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2831 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302832 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2833 ALOGD("copl(%p):send next track params in gapless", out);
2834 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2835 out->send_next_track_params = false;
2836 out->is_compr_metadata_avail = false;
2837 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002838 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302839 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302840 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002841
Ashish Jain83a6cc22016-06-28 14:34:17 +05302842 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302843 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302844 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302845 pthread_mutex_unlock(&out->lock);
2846 return -EINVAL;
2847 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302848 audio_format_t dst_format = out->hal_op_format;
2849 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302850
2851 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2852 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2853
Ashish Jain83a6cc22016-06-28 14:34:17 +05302854 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302855 dst_format,
2856 buffer,
2857 src_format,
2858 frames);
2859
Ashish Jain83a6cc22016-06-28 14:34:17 +05302860 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302861 bytes_to_write);
2862
2863 /*Convert written bytes in audio flinger format*/
2864 if (ret > 0)
2865 ret = ((ret * format_to_bitwidth_table[out->format]) /
2866 format_to_bitwidth_table[dst_format]);
2867 }
2868 } else
2869 ret = compress_write(out->compr, buffer, bytes);
2870
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302871 if (ret < 0)
2872 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302873 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302874 /*msg to cb thread only if non blocking write is enabled*/
2875 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302876 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302878 } else if (-ENETRESET == ret) {
2879 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2880 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2881 pthread_mutex_unlock(&out->lock);
2882 out_standby(&out->stream.common);
2883 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 }
Ashish Jain5106d362016-05-11 19:23:33 +05302885 if ( ret == (ssize_t)bytes && !out->non_blocking)
2886 out->written += bytes;
2887
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302888 /* Call compr start only when non-zero bytes of data is there to be rendered */
2889 if (!out->playback_started && ret > 0) {
2890 int status = compress_start(out->compr);
2891 if (status < 0) {
2892 ret = status;
2893 ALOGE("%s: compr start failed with err %d", __func__, errno);
2894 goto exit;
2895 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002896 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 out->playback_started = 1;
2898 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002899
2900 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2901 popcount(out->channel_mask),
2902 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 }
2904 pthread_mutex_unlock(&out->lock);
2905 return ret;
2906 } else {
2907 if (out->pcm) {
2908 if (out->muted)
2909 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002910
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302911 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002912
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002913 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002914
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002915 if (out->config.rate)
2916 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2917 out->config.rate;
2918
2919 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2920
2921 request_out_focus(out, ns);
2922
2923 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002924 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002925 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302926 out->convert_buffer != NULL) {
2927
2928 memcpy_by_audio_format(out->convert_buffer,
2929 out->hal_op_format,
2930 buffer,
2931 out->hal_ip_format,
2932 out->config.period_size * out->config.channels);
2933
2934 ret = pcm_write(out->pcm, out->convert_buffer,
2935 (out->config.period_size *
2936 out->config.channels *
2937 format_to_bitwidth_table[out->hal_op_format]));
2938 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002939 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302940 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002941
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002942 release_out_focus(out);
2943
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302944 if (ret < 0)
2945 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302946 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2947 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2948 else
2949 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 }
2952
2953exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302954 /* ToDo: There may be a corner case when SSR happens back to back during
2955 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302956 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302957 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302958 }
2959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 pthread_mutex_unlock(&out->lock);
2961
2962 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002963 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002964 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302965 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302966 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302967 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302968 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302969 out->standby = true;
2970 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302972 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2973 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2974 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 }
2976 return bytes;
2977}
2978
2979static int out_get_render_position(const struct audio_stream_out *stream,
2980 uint32_t *dsp_frames)
2981{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302983 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002984
2985 if (dsp_frames == NULL)
2986 return -EINVAL;
2987
2988 *dsp_frames = 0;
2989 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002990 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302991
2992 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2993 * this operation and adev_close_output_stream(where out gets reset).
2994 */
2995 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2996 *dsp_frames = get_actual_pcm_frames_rendered(out);
2997 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2998 return 0;
2999 }
3000
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003001 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303002 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303003 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303005 if (ret < 0)
3006 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303008 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003009 }
3010 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303011 if (-ENETRESET == ret) {
3012 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3013 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3014 return -EINVAL;
3015 } else if(ret < 0) {
3016 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3017 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303018 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3019 /*
3020 * Handle corner case where compress session is closed during SSR
3021 * and timestamp is queried
3022 */
3023 ALOGE(" ERROR: sound card not active, return error");
3024 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303025 } else {
3026 return 0;
3027 }
Zhou Song32a556e2015-05-05 10:46:56 +08003028 } else if (audio_is_linear_pcm(out->format)) {
3029 *dsp_frames = out->written;
3030 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003031 } else
3032 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033}
3034
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003035static int out_add_audio_effect(const struct audio_stream *stream __unused,
3036 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037{
3038 return 0;
3039}
3040
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003041static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3042 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043{
3044 return 0;
3045}
3046
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003047static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3048 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049{
3050 return -EINVAL;
3051}
3052
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003053static int out_get_presentation_position(const struct audio_stream_out *stream,
3054 uint64_t *frames, struct timespec *timestamp)
3055{
3056 struct stream_out *out = (struct stream_out *)stream;
3057 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003058 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003059
Ashish Jain5106d362016-05-11 19:23:33 +05303060 /* below piece of code is not guarded against any lock because audioFliner serializes
3061 * this operation and adev_close_output_stream( where out gets reset).
3062 */
3063 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3064 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3065 *frames = get_actual_pcm_frames_rendered(out);
3066 /* this is the best we can do */
3067 clock_gettime(CLOCK_MONOTONIC, timestamp);
3068 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3069 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3070 return 0;
3071 }
3072
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003073 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003074
Ashish Jain5106d362016-05-11 19:23:33 +05303075 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3076 ret = compress_get_tstamp(out->compr, &dsp_frames,
3077 &out->sample_rate);
3078 ALOGVV("%s rendered frames %ld sample_rate %d",
3079 __func__, dsp_frames, out->sample_rate);
3080 *frames = dsp_frames;
3081 if (ret < 0)
3082 ret = -errno;
3083 if (-ENETRESET == ret) {
3084 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3085 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3086 ret = -EINVAL;
3087 } else
3088 ret = 0;
3089 /* this is the best we can do */
3090 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003091 } else {
3092 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003093 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003094 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3095 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003096 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003097 // This adjustment accounts for buffering after app processor.
3098 // It is based on estimated DSP latency per use case, rather than exact.
3099 signed_frames -=
3100 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3101
Eric Laurent949a0892013-09-20 09:20:13 -07003102 // It would be unusual for this value to be negative, but check just in case ...
3103 if (signed_frames >= 0) {
3104 *frames = signed_frames;
3105 ret = 0;
3106 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003107 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303108 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3109 *frames = out->written;
3110 clock_gettime(CLOCK_MONOTONIC, timestamp);
3111 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003112 }
3113 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003114 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003115 return ret;
3116}
3117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118static int out_set_callback(struct audio_stream_out *stream,
3119 stream_callback_t callback, void *cookie)
3120{
3121 struct stream_out *out = (struct stream_out *)stream;
3122
3123 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003124 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003125 out->offload_callback = callback;
3126 out->offload_cookie = cookie;
3127 pthread_mutex_unlock(&out->lock);
3128 return 0;
3129}
3130
3131static int out_pause(struct audio_stream_out* stream)
3132{
3133 struct stream_out *out = (struct stream_out *)stream;
3134 int status = -ENOSYS;
3135 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003136 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003137 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003138 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303140 struct audio_device *adev = out->dev;
3141 int snd_scard_state = get_snd_card_state(adev);
3142
3143 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3144 status = compress_pause(out->compr);
3145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003147
Mingming Yin21854652016-04-13 11:54:02 -07003148 if (audio_extn_passthru_is_active()) {
3149 ALOGV("offload use case, pause passthru");
3150 audio_extn_passthru_on_pause(out);
3151 }
3152
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303153 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003154 audio_extn_dts_notify_playback_state(out->usecase, 0,
3155 out->sample_rate, popcount(out->channel_mask),
3156 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003157 }
3158 pthread_mutex_unlock(&out->lock);
3159 }
3160 return status;
3161}
3162
3163static int out_resume(struct audio_stream_out* stream)
3164{
3165 struct stream_out *out = (struct stream_out *)stream;
3166 int status = -ENOSYS;
3167 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003168 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003169 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003171 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303173 struct audio_device *adev = out->dev;
3174 int snd_scard_state = get_snd_card_state(adev);
3175
Mingming Yin21854652016-04-13 11:54:02 -07003176 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3177 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3178 pthread_mutex_lock(&out->dev->lock);
3179 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003180 pthread_mutex_unlock(&out->dev->lock);
3181 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303182 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003183 }
3184 if (!status) {
3185 out->offload_state = OFFLOAD_STATE_PLAYING;
3186 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303187 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003188 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3189 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 }
3191 pthread_mutex_unlock(&out->lock);
3192 }
3193 return status;
3194}
3195
3196static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3197{
3198 struct stream_out *out = (struct stream_out *)stream;
3199 int status = -ENOSYS;
3200 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003201 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003202 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003203 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3204 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3205 else
3206 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3207 pthread_mutex_unlock(&out->lock);
3208 }
3209 return status;
3210}
3211
3212static int out_flush(struct audio_stream_out* stream)
3213{
3214 struct stream_out *out = (struct stream_out *)stream;
3215 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003216 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003217 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003218 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003219 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3220 stop_compressed_output_l(out);
3221 out->written = 0;
3222 } else {
3223 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3224 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003225 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003226 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003227 return 0;
3228 }
3229 return -ENOSYS;
3230}
3231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232/** audio_stream_in implementation **/
3233static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3234{
3235 struct stream_in *in = (struct stream_in *)stream;
3236
3237 return in->config.rate;
3238}
3239
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003240static int in_set_sample_rate(struct audio_stream *stream __unused,
3241 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242{
3243 return -ENOSYS;
3244}
3245
3246static size_t in_get_buffer_size(const struct audio_stream *stream)
3247{
3248 struct stream_in *in = (struct stream_in *)stream;
3249
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003250 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3251 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003252 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3253 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003254
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003255 return in->config.period_size * in->af_period_multiplier *
3256 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257}
3258
3259static uint32_t in_get_channels(const struct audio_stream *stream)
3260{
3261 struct stream_in *in = (struct stream_in *)stream;
3262
3263 return in->channel_mask;
3264}
3265
3266static audio_format_t in_get_format(const struct audio_stream *stream)
3267{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003268 struct stream_in *in = (struct stream_in *)stream;
3269
3270 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271}
3272
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003273static int in_set_format(struct audio_stream *stream __unused,
3274 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275{
3276 return -ENOSYS;
3277}
3278
3279static int in_standby(struct audio_stream *stream)
3280{
3281 struct stream_in *in = (struct stream_in *)stream;
3282 struct audio_device *adev = in->dev;
3283 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303284 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3285 stream, in->usecase, use_case_table[in->usecase]);
3286
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003287 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003288 if (!in->standby && in->is_st_session) {
3289 ALOGD("%s: sound trigger pcm stop lab", __func__);
3290 audio_extn_sound_trigger_stop_lab(in);
3291 in->standby = 1;
3292 }
3293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003295 if (adev->adm_deregister_stream)
3296 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3297
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003298 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003300 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3301 voice_extn_compress_voip_close_input_stream(stream);
3302 ALOGD("VOIP input entered standby");
3303 } else {
3304 if (in->pcm) {
3305 pcm_close(in->pcm);
3306 in->pcm = NULL;
3307 }
3308 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003309 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003310 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 }
3312 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003313 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 return status;
3315}
3316
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003317static int in_dump(const struct audio_stream *stream __unused,
3318 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319{
3320 return 0;
3321}
3322
3323static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3324{
3325 struct stream_in *in = (struct stream_in *)stream;
3326 struct audio_device *adev = in->dev;
3327 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003329 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303331 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 parms = str_parms_create_str(kvpairs);
3333
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303334 if (!parms)
3335 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003336 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003337 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003338
3339 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3340 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 val = atoi(value);
3342 /* no audio source uses val == 0 */
3343 if ((in->source != val) && (val != 0)) {
3344 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003345 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3346 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3347 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003348 (in->config.rate == 8000 || in->config.rate == 16000 ||
3349 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003350 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003351 err = voice_extn_compress_voip_open_input_stream(in);
3352 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003353 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003354 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003355 }
3356 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
3358 }
3359
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003360 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3361 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003363 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 in->device = val;
3365 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003366 if (!in->standby && !in->is_st_session) {
3367 ALOGV("update input routing change");
3368 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003369 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003370 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 }
3372 }
3373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003375 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376
3377 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303378error:
Eric Laurent994a6932013-07-17 11:51:42 -07003379 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 return ret;
3381}
3382
3383static char* in_get_parameters(const struct audio_stream *stream,
3384 const char *keys)
3385{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003386 struct stream_in *in = (struct stream_in *)stream;
3387 struct str_parms *query = str_parms_create_str(keys);
3388 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003389 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003390
3391 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003392 if (reply) {
3393 str_parms_destroy(reply);
3394 }
3395 if (query) {
3396 str_parms_destroy(query);
3397 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003398 ALOGE("in_get_parameters: failed to create query or reply");
3399 return NULL;
3400 }
3401
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003402 ALOGV("%s: enter: keys - %s", __func__, keys);
3403
3404 voice_extn_in_get_parameters(in, query, reply);
3405
3406 str = str_parms_to_str(reply);
3407 str_parms_destroy(query);
3408 str_parms_destroy(reply);
3409
3410 ALOGV("%s: exit: returns - %s", __func__, str);
3411 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412}
3413
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003414static int in_set_gain(struct audio_stream_in *stream __unused,
3415 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416{
3417 return 0;
3418}
3419
3420static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3421 size_t bytes)
3422{
3423 struct stream_in *in = (struct stream_in *)stream;
3424 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303425 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303426 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303427 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003429 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303430
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003431 if (in->is_st_session) {
3432 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3433 /* Read from sound trigger HAL */
3434 audio_extn_sound_trigger_read(in, buffer, bytes);
3435 pthread_mutex_unlock(&in->lock);
3436 return bytes;
3437 }
3438
Ashish Jainbbce4322016-02-16 13:25:27 +05303439 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003440 ALOGD(" %s: sound card is not active/SSR state", __func__);
3441 ret= -EIO;;
3442 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303443 }
3444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003446 pthread_mutex_lock(&adev->lock);
3447 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3448 ret = voice_extn_compress_voip_start_input_stream(in);
3449 else
3450 ret = start_input_stream(in);
3451 pthread_mutex_unlock(&adev->lock);
3452 if (ret != 0) {
3453 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 }
3455 in->standby = 0;
3456 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003458 // what's the duration requested by the client?
3459 long ns = 0;
3460
3461 if (in->config.rate)
3462 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3463 in->config.rate;
3464
3465 request_in_focus(in, ns);
3466 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303469 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003470 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303471 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003472 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003473 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003474 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303475 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003476 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303477 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3478 if (bytes % 4 == 0) {
3479 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3480 int_buf_stream = buffer;
3481 for (size_t itt=0; itt < bytes/4 ; itt++) {
3482 int_buf_stream[itt] >>= 8;
3483 }
3484 } else {
3485 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3486 ret = -EINVAL;
3487 goto exit;
3488 }
3489 } if (ret < 0) {
3490 ret = -errno;
3491 }
3492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 }
3494
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003495 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 /*
3498 * Instead of writing zeroes here, we could trust the hardware
3499 * to always provide zeroes when muted.
3500 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303501 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3502 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 memset(buffer, 0, bytes);
3504
3505exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303506 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303507 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003508 if (-ENETRESET == ret)
3509 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 pthread_mutex_unlock(&in->lock);
3512
3513 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303514 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303515 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303516 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303517 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303518 in->standby = true;
3519 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303520 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003522 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303523 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303524 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 }
3526 return bytes;
3527}
3528
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003529static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530{
3531 return 0;
3532}
3533
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003534static int add_remove_audio_effect(const struct audio_stream *stream,
3535 effect_handle_t effect,
3536 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003538 struct stream_in *in = (struct stream_in *)stream;
3539 int status = 0;
3540 effect_descriptor_t desc;
3541
3542 status = (*effect)->get_descriptor(effect, &desc);
3543 if (status != 0)
3544 return status;
3545
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003546 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003547 pthread_mutex_lock(&in->dev->lock);
3548 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3549 in->enable_aec != enable &&
3550 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3551 in->enable_aec = enable;
3552 if (!in->standby)
3553 select_devices(in->dev, in->usecase);
3554 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003555 if (in->enable_ns != enable &&
3556 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3557 in->enable_ns = enable;
3558 if (!in->standby)
3559 select_devices(in->dev, in->usecase);
3560 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003561 pthread_mutex_unlock(&in->dev->lock);
3562 pthread_mutex_unlock(&in->lock);
3563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 return 0;
3565}
3566
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003567static int in_add_audio_effect(const struct audio_stream *stream,
3568 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569{
Eric Laurent994a6932013-07-17 11:51:42 -07003570 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003571 return add_remove_audio_effect(stream, effect, true);
3572}
3573
3574static int in_remove_audio_effect(const struct audio_stream *stream,
3575 effect_handle_t effect)
3576{
Eric Laurent994a6932013-07-17 11:51:42 -07003577 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003578 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579}
3580
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303581int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 audio_io_handle_t handle,
3583 audio_devices_t devices,
3584 audio_output_flags_t flags,
3585 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003586 struct audio_stream_out **stream_out,
3587 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588{
3589 struct audio_device *adev = (struct audio_device *)dev;
3590 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303591 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003592 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303595
3596 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3597 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003598 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303599 return -EINVAL;
3600 }
3601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3603
Mingming Yin3a941d42016-02-17 18:08:05 -08003604 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3605 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303606 devices, flags, &out->stream);
3607
3608
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003609 if (!out) {
3610 return -ENOMEM;
3611 }
3612
Haynes Mathew George204045b2015-02-25 20:32:03 -08003613 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003614 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003615 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 if (devices == AUDIO_DEVICE_NONE)
3618 devices = AUDIO_DEVICE_OUT_SPEAKER;
3619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 out->flags = flags;
3621 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003622 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003623 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003624 out->sample_rate = config->sample_rate;
3625 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3626 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003627 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003628 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003629 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303630 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631
Mingming Yin3a941d42016-02-17 18:08:05 -08003632 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3633 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3634 pthread_mutex_lock(&adev->lock);
3635 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3636 ret = read_hdmi_sink_caps(out);
3637 pthread_mutex_unlock(&adev->lock);
3638 if (ret != 0) {
3639 if (ret == -ENOSYS) {
3640 /* ignore and go with default */
3641 ret = 0;
3642 } else {
3643 ALOGE("error reading hdmi sink caps");
3644 goto error_open;
3645 }
3646 }
3647 }
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003650 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303651 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3652 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003653 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3654 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3655
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003656 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003657 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3658 /*
3659 * Do not handle stereo output in Multi-channel cases
3660 * Stereo case is handled in normal playback path
3661 */
3662 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3663 ret = AUDIO_CHANNEL_OUT_STEREO;
3664 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003665
3666 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3667 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003668 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003669 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003670 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003671
3672 if (config->sample_rate == 0)
3673 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3674 if (config->channel_mask == 0)
3675 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003676 if (config->format == 0)
3677 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003678
3679 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003680 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003681 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3683 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003685 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003687 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3688 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003689 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003690 ret = voice_extn_compress_voip_open_output_stream(out);
3691 if (ret != 0) {
3692 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3693 __func__, ret);
3694 goto error_open;
3695 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003696 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3697 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3698
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003699 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3700 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3701 ALOGE("%s: Unsupported Offload information", __func__);
3702 ret = -EINVAL;
3703 goto error_open;
3704 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003705
Mingming Yin3a941d42016-02-17 18:08:05 -08003706 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003707 if(config->offload_info.format == 0)
3708 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003709 if (config->offload_info.sample_rate == 0)
3710 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003711 }
3712
Mingming Yin90310102013-11-13 16:57:00 -08003713 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303714 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003715 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003716 ret = -EINVAL;
3717 goto error_open;
3718 }
3719
3720 out->compr_config.codec = (struct snd_codec *)
3721 calloc(1, sizeof(struct snd_codec));
3722
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003723 if (!out->compr_config.codec) {
3724 ret = -ENOMEM;
3725 goto error_open;
3726 }
3727
vivek mehta0ea887a2015-08-26 14:01:20 -07003728 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303729 out->stream.pause = out_pause;
3730 out->stream.flush = out_flush;
3731 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003732 out->usecase = get_offload_usecase(adev, true);
3733 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003734 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003735 out->stream.set_callback = out_set_callback;
3736 out->stream.pause = out_pause;
3737 out->stream.resume = out_resume;
3738 out->stream.drain = out_drain;
3739 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003740 out->usecase = get_offload_usecase(adev, false);
3741 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003742 }
vivek mehta446c3962015-09-14 10:57:35 -07003743
3744 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003745 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3746 config->format == 0 && config->sample_rate == 0 &&
3747 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003748 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003749 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3750 } else {
3751 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3752 ret = -EEXIST;
3753 goto error_open;
3754 }
vivek mehta446c3962015-09-14 10:57:35 -07003755 }
3756
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 if (config->offload_info.channel_mask)
3758 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003759 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003760 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003761 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003762 } else {
3763 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3764 ret = -EINVAL;
3765 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003766 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003767
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003768 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769 out->sample_rate = config->offload_info.sample_rate;
3770
Mingming Yin3ee55c62014-08-04 14:23:35 -07003771 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003772
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303773 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3774 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3775 audio_extn_dolby_send_ddp_endp_params(adev);
3776 audio_extn_dolby_set_dmid(adev);
3777 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003778
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003779 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003780 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003781 out->compr_config.codec->bit_rate =
3782 config->offload_info.bit_rate;
3783 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303784 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003785 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303786 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003787 /*TODO: Do we need to change it for passthrough */
3788 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789
Manish Dewangana6fc5442015-08-24 20:30:31 +05303790 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3791 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3792 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3793 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303794
3795 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3796 AUDIO_FORMAT_PCM) {
3797
3798 /*Based on platform support, configure appropriate alsa format for corresponding
3799 *hal input format.
3800 */
3801 out->compr_config.codec->format = hal_format_to_alsa(
3802 config->offload_info.format);
3803
Ashish Jain83a6cc22016-06-28 14:34:17 +05303804 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303805 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303806 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303807
3808 /*for direct PCM playback populate bit_width based on selected alsa format as
3809 *hal input format and alsa format might differ based on platform support.
3810 */
3811 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303812 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303813
3814 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3815
3816 /* Check if alsa session is configured with the same format as HAL input format,
3817 * if not then derive correct fragment size needed to accomodate the
3818 * conversion of HAL input format to alsa format.
3819 */
3820 audio_extn_utils_update_direct_pcm_fragment_size(out);
3821
3822 /*if hal input and output fragment size is different this indicates HAL input format is
3823 *not same as the alsa format
3824 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303825 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303826 /*Allocate a buffer to convert input data to the alsa configured format.
3827 *size of convert buffer is equal to the size required to hold one fragment size
3828 *worth of pcm data, this is because flinger does not write more than fragment_size
3829 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303830 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3831 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303832 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3833 ret = -ENOMEM;
3834 goto error_open;
3835 }
3836 }
3837 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3838 out->compr_config.fragment_size =
3839 audio_extn_passthru_get_buffer_size(&config->offload_info);
3840 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3841 } else {
3842 out->compr_config.fragment_size =
3843 platform_get_compress_offload_buffer_size(&config->offload_info);
3844 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3845 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003846
Amit Shekhar6f461b12014-08-01 14:52:58 -07003847 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303848 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003849
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3851 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003852
Alexy Josephaa54c872014-12-03 02:46:47 -08003853
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003854 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303855 out->send_next_track_params = false;
3856 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003857 out->offload_state = OFFLOAD_STATE_IDLE;
3858 out->playback_started = 0;
3859
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003860 audio_extn_dts_create_state_notifier_node(out->usecase);
3861
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3863 __func__, config->offload_info.version,
3864 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303865
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303866 /* Check if DSD audio format is supported in codec
3867 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303868 */
3869
3870 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303871 (!platform_check_codec_dsd_support(adev->platform) ||
3872 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303873 ret = -EINVAL;
3874 goto error_open;
3875 }
3876
Ashish Jain5106d362016-05-11 19:23:33 +05303877 /* Disable gapless if any of the following is true
3878 * passthrough playback
3879 * AV playback
3880 * Direct PCM playback
3881 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303882 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303883 (config->format == AUDIO_FORMAT_DSD) ||
3884 config->offload_info.has_video ||
3885 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303886 check_and_set_gapless_mode(adev, false);
3887 } else
3888 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003889
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303890 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003891 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3892 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303893 if (config->format == AUDIO_FORMAT_DSD) {
3894 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3895 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3896 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003897
3898 create_offload_callback_thread(out);
3899
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003900 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303901 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003902 if (ret != 0) {
3903 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3904 __func__, ret);
3905 goto error_open;
3906 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003907 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3908 if (config->sample_rate == 0)
3909 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3910 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3911 config->sample_rate != 8000) {
3912 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3913 ret = -EINVAL;
3914 goto error_open;
3915 }
3916 out->sample_rate = config->sample_rate;
3917 out->config.rate = config->sample_rate;
3918 if (config->format == AUDIO_FORMAT_DEFAULT)
3919 config->format = AUDIO_FORMAT_PCM_16_BIT;
3920 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3921 config->format = AUDIO_FORMAT_PCM_16_BIT;
3922 ret = -EINVAL;
3923 goto error_open;
3924 }
3925 out->format = config->format;
3926 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3927 out->config = pcm_config_afe_proxy_playback;
3928 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003929 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05303930 unsigned int channels = 0;
3931 /*Update config params to default if not set by the caller*/
3932 if (config->sample_rate == 0)
3933 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3934 if (config->channel_mask == AUDIO_CHANNEL_NONE)
3935 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3936 if (config->format == AUDIO_FORMAT_DEFAULT)
3937 config->format = AUDIO_FORMAT_PCM_16_BIT;
3938
3939 channels = audio_channel_count_from_out_mask(out->channel_mask);
3940
Ashish Jain83a6cc22016-06-28 14:34:17 +05303941 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3942 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003943 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3944 out->flags);
3945 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303946 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3947 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3948 out->config = pcm_config_low_latency;
3949 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3950 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3951 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05303952 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
3953 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
3954 if (out->config.period_size <= 0) {
3955 ALOGE("Invalid configuration period size is not valid");
3956 ret = -EINVAL;
3957 goto error_open;
3958 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05303959 } else {
3960 /* primary path is the default path selected if no other outputs are available/suitable */
3961 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3962 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3963 }
3964 out->hal_ip_format = format = out->format;
3965 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3966 out->hal_op_format = pcm_format_to_hal(out->config.format);
3967 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3968 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003969 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05303970 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303971 if (out->hal_ip_format != out->hal_op_format) {
3972 uint32_t buffer_size = out->config.period_size *
3973 format_to_bitwidth_table[out->hal_op_format] *
3974 out->config.channels;
3975 out->convert_buffer = calloc(1, buffer_size);
3976 if (out->convert_buffer == NULL){
3977 ALOGE("Allocation failed for convert buffer for size %d",
3978 out->compr_config.fragment_size);
3979 ret = -ENOMEM;
3980 goto error_open;
3981 }
3982 ALOGD("Convert buffer allocated of size %d", buffer_size);
3983 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 }
3985
Ashish Jain83a6cc22016-06-28 14:34:17 +05303986 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3987 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3988
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003989 /* TODO remove this hardcoding and check why width is zero*/
3990 if (out->bit_width == 0)
3991 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003992 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3993 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003994 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303995 out->bit_width, out->channel_mask,
3996 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003997 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3998 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3999 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004000 if(adev->primary_output == NULL)
4001 adev->primary_output = out;
4002 else {
4003 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004004 ret = -EEXIST;
4005 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004006 }
4007 }
4008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 /* Check if this usecase is already existing */
4010 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004011 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4012 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004015 ret = -EEXIST;
4016 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017 }
4018 pthread_mutex_unlock(&adev->lock);
4019
4020 out->stream.common.get_sample_rate = out_get_sample_rate;
4021 out->stream.common.set_sample_rate = out_set_sample_rate;
4022 out->stream.common.get_buffer_size = out_get_buffer_size;
4023 out->stream.common.get_channels = out_get_channels;
4024 out->stream.common.get_format = out_get_format;
4025 out->stream.common.set_format = out_set_format;
4026 out->stream.common.standby = out_standby;
4027 out->stream.common.dump = out_dump;
4028 out->stream.common.set_parameters = out_set_parameters;
4029 out->stream.common.get_parameters = out_get_parameters;
4030 out->stream.common.add_audio_effect = out_add_audio_effect;
4031 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4032 out->stream.get_latency = out_get_latency;
4033 out->stream.set_volume = out_set_volume;
4034 out->stream.write = out_write;
4035 out->stream.get_render_position = out_get_render_position;
4036 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004037 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004039 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004041 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004042 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043
4044 config->format = out->stream.common.get_format(&out->stream.common);
4045 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4046 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4047
4048 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304049 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004050 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004051
4052 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4053 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4054 popcount(out->channel_mask), out->playback_started);
4055
Eric Laurent994a6932013-07-17 11:51:42 -07004056 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004058
4059error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304060 if (out->convert_buffer)
4061 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004062 free(out);
4063 *stream_out = NULL;
4064 ALOGD("%s: exit: ret %d", __func__, ret);
4065 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066}
4067
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304068void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 struct audio_stream_out *stream)
4070{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004071 struct stream_out *out = (struct stream_out *)stream;
4072 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004073 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004074
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304075 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4076
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004077 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304078 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004079 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304080 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004081 if(ret != 0)
4082 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4083 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004084 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004085 out_standby(&stream->common);
4086
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004087 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004088 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004089 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004090 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004091 if (out->compr_config.codec != NULL)
4092 free(out->compr_config.codec);
4093 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004094
Ashish Jain83a6cc22016-06-28 14:34:17 +05304095 if (out->convert_buffer != NULL) {
4096 free(out->convert_buffer);
4097 out->convert_buffer = NULL;
4098 }
4099
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004100 if (adev->voice_tx_output == out)
4101 adev->voice_tx_output = NULL;
4102
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004103 pthread_cond_destroy(&out->cond);
4104 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004106 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107}
4108
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004109static void close_compress_sessions(struct audio_device *adev)
4110{
Mingming Yin7b762e72015-03-04 13:47:32 -08004111 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304112 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004113 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004114 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304115
4116 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004117 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304118 if (is_offload_usecase(usecase->id)) {
4119 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004120 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4121 out = usecase->stream.out;
4122 pthread_mutex_unlock(&adev->lock);
4123 out_standby(&out->stream.common);
4124 pthread_mutex_lock(&adev->lock);
4125 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304126 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004127 }
4128 pthread_mutex_unlock(&adev->lock);
4129}
4130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4132{
4133 struct audio_device *adev = (struct audio_device *)dev;
4134 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004136 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004137 int ret;
4138 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004140 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304143 if (!parms)
4144 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004145 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4146 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304147 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304148 if (strstr(snd_card_status, "OFFLINE")) {
4149 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304150 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004151 //close compress sessions on OFFLINE status
4152 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304153 } else if (strstr(snd_card_status, "ONLINE")) {
4154 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304155 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004156 //send dts hpx license if enabled
4157 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304158 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304159 }
4160
4161 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004162 status = voice_set_parameters(adev, parms);
4163 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004164 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004166 status = platform_set_parameters(adev->platform, parms);
4167 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004168 goto done;
4169
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004170 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4171 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004172 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4174 adev->bluetooth_nrec = true;
4175 else
4176 adev->bluetooth_nrec = false;
4177 }
4178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004179 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4180 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4182 adev->screen_off = false;
4183 else
4184 adev->screen_off = true;
4185 }
4186
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004187 ret = str_parms_get_int(parms, "rotation", &val);
4188 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004189 bool reverse_speakers = false;
4190 switch(val) {
4191 // FIXME: note that the code below assumes that the speakers are in the correct placement
4192 // relative to the user when the device is rotated 90deg from its default rotation. This
4193 // assumption is device-specific, not platform-specific like this code.
4194 case 270:
4195 reverse_speakers = true;
4196 break;
4197 case 0:
4198 case 90:
4199 case 180:
4200 break;
4201 default:
4202 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004203 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004204 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004205 if (status == 0) {
4206 if (adev->speaker_lr_swap != reverse_speakers) {
4207 adev->speaker_lr_swap = reverse_speakers;
4208 // only update the selected device if there is active pcm playback
4209 struct audio_usecase *usecase;
4210 struct listnode *node;
4211 list_for_each(node, &adev->usecase_list) {
4212 usecase = node_to_item(node, struct audio_usecase, list);
4213 if (usecase->type == PCM_PLAYBACK) {
4214 select_devices(adev, usecase->id);
4215 break;
4216 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004217 }
4218 }
4219 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004220 }
4221
Mingming Yin514a8bc2014-07-29 15:22:21 -07004222 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4223 if (ret >= 0) {
4224 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4225 adev->bt_wb_speech_enabled = true;
4226 else
4227 adev->bt_wb_speech_enabled = false;
4228 }
4229
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004230 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4231 if (ret >= 0) {
4232 val = atoi(value);
4233 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004234 ALOGV("cache new ext disp type and edid");
4235 ret = platform_get_ext_disp_type(adev->platform);
4236 if (ret < 0) {
4237 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
4238 return ret;
4239 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004240 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004241 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004242 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004243 /*
4244 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4245 * Per AudioPolicyManager, USB device is higher priority than WFD.
4246 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4247 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4248 * starting voice call on USB
4249 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004250 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4251 if (ret >= 0) {
4252 audio_extn_usb_add_device(val, atoi(value));
4253 }
vivek mehta344576a2016-04-12 18:56:03 -07004254 ALOGV("detected USB connect .. disable proxy");
4255 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004256 }
4257 }
4258
4259 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4260 if (ret >= 0) {
4261 val = atoi(value);
4262 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4263 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004264 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004265 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004266 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004267 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4268 if (ret >= 0) {
4269 audio_extn_usb_remove_device(val, atoi(value));
4270 }
vivek mehta344576a2016-04-12 18:56:03 -07004271 ALOGV("detected USB disconnect .. enable proxy");
4272 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004273 }
4274 }
4275
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304276 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4277 if (ret >= 0) {
4278 struct audio_usecase *usecase;
4279 struct listnode *node;
4280 list_for_each(node, &adev->usecase_list) {
4281 usecase = node_to_item(node, struct audio_usecase, list);
4282 if ((usecase->type == PCM_PLAYBACK) &&
4283 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4284 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304285 lock_output_stream(usecase->stream.out);
4286 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304287 //force device switch to re configure encoder
4288 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304289 audio_extn_a2dp_set_handoff_mode(false);
4290 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304291 break;
4292 }
4293 }
4294 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304295 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004296done:
4297 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004298 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304299error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004300 ALOGV("%s: exit with code(%d)", __func__, status);
4301 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302}
4303
4304static char* adev_get_parameters(const struct audio_hw_device *dev,
4305 const char *keys)
4306{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004307 struct audio_device *adev = (struct audio_device *)dev;
4308 struct str_parms *reply = str_parms_create();
4309 struct str_parms *query = str_parms_create_str(keys);
4310 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304311 char value[256] = {0};
4312 int ret = 0;
4313
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004314 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004315 if (reply) {
4316 str_parms_destroy(reply);
4317 }
4318 if (query) {
4319 str_parms_destroy(query);
4320 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004321 ALOGE("adev_get_parameters: failed to create query or reply");
4322 return NULL;
4323 }
4324
Naresh Tannirud7205b62014-06-20 02:54:48 +05304325 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4326 sizeof(value));
4327 if (ret >=0) {
4328 int val = 1;
4329 pthread_mutex_lock(&adev->snd_card_status.lock);
4330 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4331 val = 0;
4332 pthread_mutex_unlock(&adev->snd_card_status.lock);
4333 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4334 goto exit;
4335 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004336
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004337 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004338 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004339 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004340 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304341 pthread_mutex_unlock(&adev->lock);
4342
Naresh Tannirud7205b62014-06-20 02:54:48 +05304343exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004344 str = str_parms_to_str(reply);
4345 str_parms_destroy(query);
4346 str_parms_destroy(reply);
4347
4348 ALOGV("%s: exit: returns - %s", __func__, str);
4349 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350}
4351
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004352static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353{
4354 return 0;
4355}
4356
4357static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4358{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004359 int ret;
4360 struct audio_device *adev = (struct audio_device *)dev;
4361 pthread_mutex_lock(&adev->lock);
4362 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004363 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004364 pthread_mutex_unlock(&adev->lock);
4365 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366}
4367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004368static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4369 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370{
4371 return -ENOSYS;
4372}
4373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004374static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4375 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376{
4377 return -ENOSYS;
4378}
4379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004380static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4381 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382{
4383 return -ENOSYS;
4384}
4385
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004386static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4387 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388{
4389 return -ENOSYS;
4390}
4391
4392static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4393{
4394 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 pthread_mutex_lock(&adev->lock);
4397 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004398 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004400 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004401 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004402 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004403 adev->current_call_output = NULL;
4404 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 }
4406 pthread_mutex_unlock(&adev->lock);
4407 return 0;
4408}
4409
4410static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4411{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004412 int ret;
4413
4414 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004415 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004416 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4417 pthread_mutex_unlock(&adev->lock);
4418
4419 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420}
4421
4422static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4423{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004424 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425 return 0;
4426}
4427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004428static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429 const struct audio_config *config)
4430{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004431 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004433 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4434 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004435}
4436
4437static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004438 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 audio_devices_t devices,
4440 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004441 struct audio_stream_in **stream_in,
4442 audio_input_flags_t flags __unused,
4443 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004444 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445{
4446 struct audio_device *adev = (struct audio_device *)dev;
4447 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004448 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004449 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004450 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304453 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4454 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304456 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457
4458 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004459
4460 if (!in) {
4461 ALOGE("failed to allocate input stream");
4462 return -ENOMEM;
4463 }
4464
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304465 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304466 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4467 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004468 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004469 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471 in->stream.common.get_sample_rate = in_get_sample_rate;
4472 in->stream.common.set_sample_rate = in_set_sample_rate;
4473 in->stream.common.get_buffer_size = in_get_buffer_size;
4474 in->stream.common.get_channels = in_get_channels;
4475 in->stream.common.get_format = in_get_format;
4476 in->stream.common.set_format = in_set_format;
4477 in->stream.common.standby = in_standby;
4478 in->stream.common.dump = in_dump;
4479 in->stream.common.set_parameters = in_set_parameters;
4480 in->stream.common.get_parameters = in_get_parameters;
4481 in->stream.common.add_audio_effect = in_add_audio_effect;
4482 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4483 in->stream.set_gain = in_set_gain;
4484 in->stream.read = in_read;
4485 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4486
4487 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004488 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 in->standby = 1;
4491 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004492 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004493 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004494
4495 /* Update config params with the requested sample rate and channels */
4496 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004497 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4498 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4499 is_low_latency = true;
4500#if LOW_LATENCY_CAPTURE_USE_CASE
4501 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4502#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004503 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004504 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004505
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004506 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004507 if (in->realtime) {
4508 in->config = pcm_config_audio_capture_rt;
4509 in->sample_rate = in->config.rate;
4510 in->af_period_multiplier = af_period_multiplier;
4511 } else {
4512 in->config = pcm_config_audio_capture;
4513 in->config.rate = config->sample_rate;
4514 in->sample_rate = config->sample_rate;
4515 in->af_period_multiplier = 1;
4516 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304517 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004519 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304520 if (adev->mode != AUDIO_MODE_IN_CALL) {
4521 ret = -EINVAL;
4522 goto err_open;
4523 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004524 if (config->sample_rate == 0)
4525 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4526 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4527 config->sample_rate != 8000) {
4528 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4529 ret = -EINVAL;
4530 goto err_open;
4531 }
4532 if (config->format == AUDIO_FORMAT_DEFAULT)
4533 config->format = AUDIO_FORMAT_PCM_16_BIT;
4534 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4535 config->format = AUDIO_FORMAT_PCM_16_BIT;
4536 ret = -EINVAL;
4537 goto err_open;
4538 }
4539
4540 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4541 in->config = pcm_config_afe_proxy_record;
4542 in->config.channels = channel_count;
4543 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304544 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304545 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4546 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004547 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004548 audio_extn_compr_cap_format_supported(config->format) &&
4549 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004550 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004551 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304552 /* restrict 24 bit capture for unprocessed source only
4553 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4554 */
4555 if (config->format == AUDIO_FORMAT_DEFAULT) {
4556 config->format = AUDIO_FORMAT_PCM_16_BIT;
4557 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4558 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4559 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4560 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4561 bool ret_error = false;
4562 in->bit_width = 24;
4563 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4564 from HAL is 24_packed and 8_24
4565 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4566 24_packed return error indicating supported format is 24_packed
4567 *> In case of any other source requesting 24 bit or float return error
4568 indicating format supported is 16 bit only.
4569
4570 on error flinger will retry with supported format passed
4571 */
4572 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4573 (source != AUDIO_SOURCE_CAMCORDER)) {
4574 config->format = AUDIO_FORMAT_PCM_16_BIT;
4575 if( config->sample_rate > 48000)
4576 config->sample_rate = 48000;
4577 ret_error = true;
4578 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4579 in->config.format = PCM_FORMAT_S24_3LE;
4580 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4581 in->config.format = PCM_FORMAT_S24_LE;
4582 } else {
4583 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4584 ret_error = true;
4585 }
4586
4587 if (ret_error) {
4588 ret = -EINVAL;
4589 goto err_open;
4590 }
4591 }
4592
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004593 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004594 if (!in->realtime) {
4595 in->format = config->format;
4596 frame_size = audio_stream_in_frame_size(&in->stream);
4597 buffer_size = get_input_buffer_size(config->sample_rate,
4598 config->format,
4599 channel_count,
4600 is_low_latency);
4601 in->config.period_size = buffer_size / frame_size;
4602 }
4603
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004604 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4605 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4606 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004607 (in->config.rate == 8000 || in->config.rate == 16000 ||
4608 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004609 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4610 voice_extn_compress_voip_open_input_stream(in);
4611 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004614 /* This stream could be for sound trigger lab,
4615 get sound trigger pcm if present */
4616 audio_extn_sound_trigger_check_and_get_session(in);
4617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004619 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004620 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621
4622err_open:
4623 free(in);
4624 *stream_in = NULL;
4625 return ret;
4626}
4627
4628static void adev_close_input_stream(struct audio_hw_device *dev,
4629 struct audio_stream_in *stream)
4630{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004631 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004632 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004633 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304634
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304635 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004636
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304637 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004638 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304639
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004640 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304641 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004642 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304643 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004644 if (ret != 0)
4645 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4646 __func__, ret);
4647 } else
4648 in_standby(&stream->common);
4649
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004650 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004651 audio_extn_ssr_deinit();
4652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653
Mingming Yine62d7842013-10-25 16:26:03 -07004654 if(audio_extn_compr_cap_enabled() &&
4655 audio_extn_compr_cap_format_supported(in->config.format))
4656 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004657
Mingming Yinfd7607b2016-01-22 12:48:44 -08004658 if (in->is_st_session) {
4659 ALOGV("%s: sound trigger pcm stop lab", __func__);
4660 audio_extn_sound_trigger_stop_lab(in);
4661 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004662 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 return;
4664}
4665
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004666static int adev_dump(const audio_hw_device_t *device __unused,
4667 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668{
4669 return 0;
4670}
4671
4672static int adev_close(hw_device_t *device)
4673{
4674 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004675
4676 if (!adev)
4677 return 0;
4678
4679 pthread_mutex_lock(&adev_init_lock);
4680
4681 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004682 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004683 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304684 if (audio_extn_qaf_is_enabled())
4685 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004686 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004687 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004688 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004689 free(adev->snd_dev_ref_cnt);
4690 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004691 if (adev->adm_deinit)
4692 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004693 free(device);
4694 adev = NULL;
4695 }
4696 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698 return 0;
4699}
4700
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004701/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4702 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4703 * just that it _might_ work.
4704 */
4705static int period_size_is_plausible_for_low_latency(int period_size)
4706{
4707 switch (period_size) {
4708 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004709 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004710 case 240:
4711 case 320:
4712 case 480:
4713 return 1;
4714 default:
4715 return 0;
4716 }
4717}
4718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719static int adev_open(const hw_module_t *module, const char *name,
4720 hw_device_t **device)
4721{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304722 int ret;
4723
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004724 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4726
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004727 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004728 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004729 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004730 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004731 ALOGD("%s: returning existing instance of adev", __func__);
4732 ALOGD("%s: exit", __func__);
4733 pthread_mutex_unlock(&adev_init_lock);
4734 return 0;
4735 }
4736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737 adev = calloc(1, sizeof(struct audio_device));
4738
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004739 if (!adev) {
4740 pthread_mutex_unlock(&adev_init_lock);
4741 return -ENOMEM;
4742 }
4743
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004744 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4747 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4748 adev->device.common.module = (struct hw_module_t *)module;
4749 adev->device.common.close = adev_close;
4750
4751 adev->device.init_check = adev_init_check;
4752 adev->device.set_voice_volume = adev_set_voice_volume;
4753 adev->device.set_master_volume = adev_set_master_volume;
4754 adev->device.get_master_volume = adev_get_master_volume;
4755 adev->device.set_master_mute = adev_set_master_mute;
4756 adev->device.get_master_mute = adev_get_master_mute;
4757 adev->device.set_mode = adev_set_mode;
4758 adev->device.set_mic_mute = adev_set_mic_mute;
4759 adev->device.get_mic_mute = adev_get_mic_mute;
4760 adev->device.set_parameters = adev_set_parameters;
4761 adev->device.get_parameters = adev_get_parameters;
4762 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4763 adev->device.open_output_stream = adev_open_output_stream;
4764 adev->device.close_output_stream = adev_close_output_stream;
4765 adev->device.open_input_stream = adev_open_input_stream;
4766 adev->device.close_input_stream = adev_close_input_stream;
4767 adev->device.dump = adev_dump;
4768
4769 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004771 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004772 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004773 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004775 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004776 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004777 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004778 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004779 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004780 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004781 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004782 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304783 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304784 adev->perf_lock_opts[0] = 0x101;
4785 adev->perf_lock_opts[1] = 0x20E;
4786 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304787
4788 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4789 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004791 adev->platform = platform_init(adev);
4792 if (!adev->platform) {
4793 free(adev->snd_dev_ref_cnt);
4794 free(adev);
4795 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4796 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004797 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304798 pthread_mutex_destroy(&adev->lock);
4799 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004800 return -EINVAL;
4801 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004802
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304803 if (audio_extn_qaf_is_enabled()) {
4804 ret = audio_extn_qaf_init(adev);
4805 if (ret < 0) {
4806 free(adev);
4807 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4808 *device = NULL;
4809 pthread_mutex_unlock(&adev_init_lock);
4810 pthread_mutex_destroy(&adev->lock);
4811 return ret;
4812 }
4813
4814 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4815 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4816 }
4817
Naresh Tanniru4c630392014-05-12 01:05:52 +05304818 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4819
Eric Laurentc4aef752013-09-12 17:45:53 -07004820 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4821 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4822 if (adev->visualizer_lib == NULL) {
4823 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4824 } else {
4825 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4826 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004827 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004828 "visualizer_hal_start_output");
4829 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004830 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004831 "visualizer_hal_stop_output");
4832 }
4833 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004834 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004835 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004836 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004837
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004838 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4839 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4840 if (adev->offload_effects_lib == NULL) {
4841 ALOGE("%s: DLOPEN failed for %s", __func__,
4842 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4843 } else {
4844 ALOGV("%s: DLOPEN successful for %s", __func__,
4845 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4846 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304847 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004848 "offload_effects_bundle_hal_start_output");
4849 adev->offload_effects_stop_output =
4850 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4851 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004852 adev->offload_effects_set_hpx_state =
4853 (int (*)(bool))dlsym(adev->offload_effects_lib,
4854 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304855 adev->offload_effects_get_parameters =
4856 (void (*)(struct str_parms *, struct str_parms *))
4857 dlsym(adev->offload_effects_lib,
4858 "offload_effects_bundle_get_parameters");
4859 adev->offload_effects_set_parameters =
4860 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4861 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004862 }
4863 }
4864
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004865 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4866 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4867 if (adev->adm_lib == NULL) {
4868 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4869 } else {
4870 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4871 adev->adm_init = (adm_init_t)
4872 dlsym(adev->adm_lib, "adm_init");
4873 adev->adm_deinit = (adm_deinit_t)
4874 dlsym(adev->adm_lib, "adm_deinit");
4875 adev->adm_register_input_stream = (adm_register_input_stream_t)
4876 dlsym(adev->adm_lib, "adm_register_input_stream");
4877 adev->adm_register_output_stream = (adm_register_output_stream_t)
4878 dlsym(adev->adm_lib, "adm_register_output_stream");
4879 adev->adm_deregister_stream = (adm_deregister_stream_t)
4880 dlsym(adev->adm_lib, "adm_deregister_stream");
4881 adev->adm_request_focus = (adm_request_focus_t)
4882 dlsym(adev->adm_lib, "adm_request_focus");
4883 adev->adm_abandon_focus = (adm_abandon_focus_t)
4884 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004885 adev->adm_set_config = (adm_set_config_t)
4886 dlsym(adev->adm_lib, "adm_set_config");
4887 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4888 dlsym(adev->adm_lib, "adm_request_focus_v2");
4889 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4890 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4891 adev->adm_on_routing_change = (adm_on_routing_change_t)
4892 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004893 }
4894 }
4895
Mingming Yin514a8bc2014-07-29 15:22:21 -07004896 adev->bt_wb_speech_enabled = false;
4897
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004898 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899 *device = &adev->device.common;
4900
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004901 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4902 &adev->streams_output_cfg_list);
4903
Kiran Kandi910e1862013-10-29 13:29:42 -07004904 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004905
4906 char value[PROPERTY_VALUE_MAX];
4907 int trial;
4908 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4909 trial = atoi(value);
4910 if (period_size_is_plausible_for_low_latency(trial)) {
4911 pcm_config_low_latency.period_size = trial;
4912 pcm_config_low_latency.start_threshold = trial / 4;
4913 pcm_config_low_latency.avail_min = trial / 4;
4914 configured_low_latency_capture_period_size = trial;
4915 }
4916 }
4917 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4918 trial = atoi(value);
4919 if (period_size_is_plausible_for_low_latency(trial)) {
4920 configured_low_latency_capture_period_size = trial;
4921 }
4922 }
4923
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004924 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4925 af_period_multiplier = atoi(value);
4926 if (af_period_multiplier < 0)
4927 af_period_multiplier = 2;
4928 else if (af_period_multiplier > 4)
4929 af_period_multiplier = 4;
4930
4931 ALOGV("new period_multiplier = %d", af_period_multiplier);
4932 }
4933
vivek mehta446c3962015-09-14 10:57:35 -07004934 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004935 pthread_mutex_unlock(&adev_init_lock);
4936
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004937 if (adev->adm_init)
4938 adev->adm_data = adev->adm_init();
4939
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304940 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004941 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004942 return 0;
4943}
4944
4945static struct hw_module_methods_t hal_module_methods = {
4946 .open = adev_open,
4947};
4948
4949struct audio_module HAL_MODULE_INFO_SYM = {
4950 .common = {
4951 .tag = HARDWARE_MODULE_TAG,
4952 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4953 .hal_api_version = HARDWARE_HAL_API_VERSION,
4954 .id = AUDIO_HARDWARE_MODULE_ID,
4955 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004956 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957 .methods = &hal_module_methods,
4958 },
4959};