blob: b354c6a309ce18720889e0be7e633a17233a488b [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700386 if (adev->adm_request_focus_v2)
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 else if (adev->adm_request_focus)
389 adev->adm_request_focus(adev->adm_data, out->handle);
390}
391
392static void request_in_focus(struct stream_in *in, long ns)
393{
394 struct audio_device *adev = in->dev;
395
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700396 if (adev->adm_request_focus_v2)
397 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
398 else if (adev->adm_request_focus)
399 adev->adm_request_focus(adev->adm_data, in->capture_handle);
400}
401
402static void release_out_focus(struct stream_out *out)
403{
404 struct audio_device *adev = out->dev;
405
406 if (adev->adm_abandon_focus)
407 adev->adm_abandon_focus(adev->adm_data, out->handle);
408}
409
410static void release_in_focus(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
415}
416
vivek mehtaa76401a2015-04-24 14:12:15 -0700417__attribute__ ((visibility ("default")))
418bool audio_hw_send_gain_dep_calibration(int level) {
419 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700420 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700421
422 pthread_mutex_lock(&adev_init_lock);
423
424 if (adev != NULL && adev->platform != NULL) {
425 pthread_mutex_lock(&adev->lock);
426 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700427
428 // if cal set fails, cache level info
429 // if cal set succeds, reset known last cal set
430 if (!ret_val)
431 last_known_cal_step = level;
432 else if (last_known_cal_step != -1)
433 last_known_cal_step = -1;
434
vivek mehtaa76401a2015-04-24 14:12:15 -0700435 pthread_mutex_unlock(&adev->lock);
436 } else {
437 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
438 }
439
440 pthread_mutex_unlock(&adev_init_lock);
441
442 return ret_val;
443}
444
Ashish Jain5106d362016-05-11 19:23:33 +0530445static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
446{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800447 bool gapless_enabled = false;
448 const char *mixer_ctl_name = "Compress Gapless Playback";
449 struct mixer_ctl *ctl;
450
451 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530452 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
453
454 /*Disable gapless if its AV playback*/
455 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456
457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
458 if (!ctl) {
459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
460 __func__, mixer_ctl_name);
461 return -EINVAL;
462 }
463
464 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
465 ALOGE("%s: Could not set gapless mode %d",
466 __func__, gapless_enabled);
467 return -EINVAL;
468 }
469 return 0;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700472static bool is_supported_format(audio_format_t format)
473{
Eric Laurent86e17132013-09-12 17:49:30 -0700474 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530475 format == AUDIO_FORMAT_AAC_LC ||
476 format == AUDIO_FORMAT_AAC_HE_V1 ||
477 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530478 format == AUDIO_FORMAT_AAC_ADTS_LC ||
479 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530481 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
482 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530483 format == AUDIO_FORMAT_PCM_FLOAT ||
484 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700485 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530486 format == AUDIO_FORMAT_AC3 ||
487 format == AUDIO_FORMAT_E_AC3 ||
488 format == AUDIO_FORMAT_DTS ||
489 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800490 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530491 format == AUDIO_FORMAT_ALAC ||
492 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530493 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800495 format == AUDIO_FORMAT_WMA ||
496 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800497 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498
499 return false;
500}
501
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700502static inline bool is_mmap_usecase(audio_usecase_t uc_id)
503{
504 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
505 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
506}
507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508static int get_snd_codec_id(audio_format_t format)
509{
510 int id = 0;
511
Ashish Jainf9b78162014-08-25 20:36:25 +0530512 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513 case AUDIO_FORMAT_MP3:
514 id = SND_AUDIOCODEC_MP3;
515 break;
516 case AUDIO_FORMAT_AAC:
517 id = SND_AUDIOCODEC_AAC;
518 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530519 case AUDIO_FORMAT_AAC_ADTS:
520 id = SND_AUDIOCODEC_AAC;
521 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700522 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800523 id = SND_AUDIOCODEC_PCM;
524 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700525 case AUDIO_FORMAT_FLAC:
526 id = SND_AUDIOCODEC_FLAC;
527 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 case AUDIO_FORMAT_ALAC:
529 id = SND_AUDIOCODEC_ALAC;
530 break;
531 case AUDIO_FORMAT_APE:
532 id = SND_AUDIOCODEC_APE;
533 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530534 case AUDIO_FORMAT_DSD:
535 id = SND_AUDIOCODEC_DSD;
536 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530537 case AUDIO_FORMAT_VORBIS:
538 id = SND_AUDIOCODEC_VORBIS;
539 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800540 case AUDIO_FORMAT_WMA:
541 id = SND_AUDIOCODEC_WMA;
542 break;
543 case AUDIO_FORMAT_WMA_PRO:
544 id = SND_AUDIOCODEC_WMA_PRO;
545 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530546 case AUDIO_FORMAT_AC3:
547 id = SND_AUDIOCODEC_AC3;
548 break;
549 case AUDIO_FORMAT_E_AC3:
550 case AUDIO_FORMAT_E_AC3_JOC:
551 id = SND_AUDIOCODEC_EAC3;
552 break;
553 case AUDIO_FORMAT_DTS:
554 case AUDIO_FORMAT_DTS_HD:
555 id = SND_AUDIOCODEC_DTS;
556 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557 default:
Mingming Yin90310102013-11-13 16:57:00 -0800558 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700559 }
560
561 return id;
562}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800563
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530564int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530565{
566 int snd_scard_state;
567
568 if (!adev)
569 return SND_CARD_STATE_OFFLINE;
570
571 pthread_mutex_lock(&adev->snd_card_status.lock);
572 snd_scard_state = adev->snd_card_status.state;
573 pthread_mutex_unlock(&adev->snd_card_status.lock);
574
575 return snd_scard_state;
576}
577
578static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
579{
580 if (!adev)
581 return -ENOSYS;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700584 if (adev->snd_card_status.state != snd_scard_state) {
585 adev->snd_card_status.state = snd_scard_state;
586 platform_snd_card_update(adev->platform, snd_scard_state);
587 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530588 pthread_mutex_unlock(&adev->snd_card_status.lock);
589
590 return 0;
591}
592
Avinash Vaish71a8b972014-07-24 15:36:33 +0530593static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
594 struct audio_usecase *uc_info)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598
599 if (uc_info == NULL)
600 return -EINVAL;
601
602 /* Re-route all voice usecases on the shared backend other than the
603 specified usecase to new snd devices */
604 list_for_each(node, &adev->usecase_list) {
605 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800606 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530607 enable_audio_route(adev, usecase);
608 }
609 return 0;
610}
611
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530614 ALOGV("%s", __func__);
615 audio_route_apply_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = true;
618}
619
620static void disable_asrc_mode(struct audio_device *adev)
621{
622 ALOGV("%s", __func__);
623 audio_route_reset_and_update_path(adev->audio_route,
624 "asrc-mode");
625 adev->asrc_mode_enabled = false;
626}
627
628/*
629 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
630 * 44.1 or Native DSD backends are enabled for any of current use case.
631 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
632 * - Disable current mix path use case(Headphone backend) and re-enable it with
633 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
634 * e.g. Naitve DSD or Headphone 44.1 -> + 48
635 */
636static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
637{
638 ALOGV("%s snd device %d", __func__, snd_device);
639 int new_backend_idx = platform_get_backend_index(snd_device);
640
641 if (((new_backend_idx == HEADPHONE_BACKEND) ||
642 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
643 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
644 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530645 struct listnode *node = NULL;
646 struct audio_usecase *uc = NULL;
647 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530648 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649
650 list_for_each(node, &adev->usecase_list) {
651 uc = node_to_item(node, struct audio_usecase, list);
652 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
655
656 if((new_backend_idx == HEADPHONE_BACKEND) &&
657 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
658 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530659 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
660 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 enable_asrc_mode(adev);
662 break;
663 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
664 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
665 (usecase_backend_idx == HEADPHONE_BACKEND)) {
666 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
667 __func__);
668 disable_audio_route(adev, uc);
669 disable_snd_device(adev, uc->out_snd_device);
670 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
671 if (new_backend_idx == DSD_NATIVE_BACKEND)
672 audio_route_apply_and_update_path(adev->audio_route,
673 "hph-true-highquality-mode");
674 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
675 (curr_out->bit_width >= 24))
676 audio_route_apply_and_update_path(adev->audio_route,
677 "hph-highquality-mode");
678 enable_asrc_mode(adev);
679 enable_snd_device(adev, uc->out_snd_device);
680 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530681 break;
682 }
683 }
684 }
685 }
686}
687
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700688int pcm_ioctl(struct pcm *pcm, int request, ...)
689{
690 va_list ap;
691 void * arg;
692 int pcm_fd = *(int*)pcm;
693
694 va_start(ap, request);
695 arg = va_arg(ap, void *);
696 va_end(ap);
697
698 return ioctl(pcm_fd, request, arg);
699}
700
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700701int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
707 if (usecase == NULL)
708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
711
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800717#ifdef DS1_DOLBY_DAP_ENABLED
718 audio_extn_dolby_set_dmid(adev);
719 audio_extn_dolby_set_endpoint(adev);
720#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700721 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700722 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530723 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700724 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530725 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800726 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700727 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700728 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 ALOGV("%s: exit", __func__);
731 return 0;
732}
733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700734int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700738 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530740 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 return -EINVAL;
742
743 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (usecase->type == PCM_CAPTURE)
745 snd_device = usecase->in_snd_device;
746 else
747 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700752 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530753 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700758int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530761 int i, num_devices = 0;
762 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700763 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
764
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 if (snd_device < SND_DEVICE_MIN ||
766 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800767 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return -EINVAL;
769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770
771 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772
773 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
774 ALOGE("%s: Invalid sound device returned", __func__);
775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700778 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 return 0;
781 }
782
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530783
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700784 if (audio_extn_spkr_prot_is_enabled())
785 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800787 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
788 audio_extn_spkr_prot_is_enabled()) {
789 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
791 return -EINVAL;
792 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200793 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800794 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800795 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200796 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800797 return -EINVAL;
798 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530799 } else if (platform_can_split_snd_device(adev->platform, snd_device,
800 &num_devices, new_snd_devices)) {
801 for (i = 0; i < num_devices; i++) {
802 enable_snd_device(adev, new_snd_devices[i]);
803 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700805 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530806
807 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
808 (audio_extn_a2dp_start_playback() < 0)) {
809 ALOGE(" fail to configure A2dp control path ");
810 return -EINVAL;
811 }
812
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700813 /* due to the possibility of calibration overwrite between listen
814 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700815 audio_extn_sound_trigger_update_device_status(snd_device,
816 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530817 audio_extn_listen_update_device_status(snd_device,
818 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700819 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700820 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700821 audio_extn_sound_trigger_update_device_status(snd_device,
822 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530823 audio_extn_listen_update_device_status(snd_device,
824 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700825 return -EINVAL;
826 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300827 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700828 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530829
830 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
831 !adev->native_playback_enabled &&
832 audio_is_true_native_stream_active(adev)) {
833 ALOGD("%s: %d: napb: enabling native mode in hardware",
834 __func__, __LINE__);
835 audio_route_apply_and_update_path(adev->audio_route,
836 "true-native-mode");
837 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840 return 0;
841}
842
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700843int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700844 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800845{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530846 int i, num_devices = 0;
847 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700848 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
849
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 if (snd_device < SND_DEVICE_MIN ||
851 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800852 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800853 return -EINVAL;
854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
856 ALOGE("%s: device ref cnt is already 0", __func__);
857 return -EINVAL;
858 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700861
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
863 ALOGE("%s: Invalid sound device returned", __func__);
864 return -EINVAL;
865 }
866
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700868 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530869
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800870 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
871 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700872 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 } else if (platform_can_split_snd_device(adev->platform, snd_device,
874 &num_devices, new_snd_devices)) {
875 for (i = 0; i < num_devices; i++) {
876 disable_snd_device(adev, new_snd_devices[i]);
877 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300878 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700879 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300880 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700881
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530882 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
883 audio_extn_a2dp_stop_playback();
884
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700885 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530886 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530887 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
888 adev->native_playback_enabled) {
889 ALOGD("%s: %d: napb: disabling native mode in hardware",
890 __func__, __LINE__);
891 audio_route_reset_and_update_path(adev->audio_route,
892 "true-native-mode");
893 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530894 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
895 adev->asrc_mode_enabled) {
896 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530897 disable_asrc_mode(adev);
898 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530899 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530900
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200901 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700902 audio_extn_sound_trigger_update_device_status(snd_device,
903 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530904 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800905 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 return 0;
909}
910
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530912 struct audio_usecase *uc_info,
913 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914{
915 struct listnode *node;
916 struct audio_usecase *usecase;
917 bool switch_device[AUDIO_USECASE_MAX];
918 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530919 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 /*
921 * This function is to make sure that all the usecases that are active on
922 * the hardware codec backend are always routed to any one device that is
923 * handled by the hardware codec.
924 * For example, if low-latency and deep-buffer usecases are currently active
925 * on speaker and out_set_parameters(headset) is received on low-latency
926 * output, then we have to make sure deep-buffer is also switched to headset,
927 * because of the limitation that both the devices cannot be enabled
928 * at the same time as they share the same backend.
929 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700930 /*
931 * This call is to check if we need to force routing for a particular stream
932 * If there is a backend configuration change for the device when a
933 * new stream starts, then ADM needs to be closed and re-opened with the new
934 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800935 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700936 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800937 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
938 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530939 /* For a2dp device reconfigure all active sessions
940 * with new AFE encoder format based on a2dp state
941 */
942 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
943 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
944 audio_extn_a2dp_is_force_device_switch()) {
945 force_routing = true;
946 force_restart_session = true;
947 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530948 ALOGD("%s:becf: force routing %d", __func__, force_routing);
949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800951 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800952 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 for (i = 0; i < AUDIO_USECASE_MAX; i++)
954 switch_device[i] = false;
955
956 list_for_each(node, &adev->usecase_list) {
957 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800958
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530959 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
960 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530961 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530962 platform_get_snd_device_name(usecase->out_snd_device),
963 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800964 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530965 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530966 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530967 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
968 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530969 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530970 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530971 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
972
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530973 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
974 __func__, use_case_table[usecase->id],
975 platform_get_snd_device_name(usecase->out_snd_device));
976 disable_audio_route(adev, usecase);
977 switch_device[usecase->id] = true;
978 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980 }
981
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
983 num_uc_to_switch);
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700986 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530988 /* Make sure the previous devices to be disabled first and then enable the
989 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 list_for_each(node, &adev->usecase_list) {
991 usecase = node_to_item(node, struct audio_usecase, list);
992 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700993 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 }
995 }
996
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700997 list_for_each(node, &adev->usecase_list) {
998 usecase = node_to_item(node, struct audio_usecase, list);
999 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001000 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 /* Re-route all the usecases on the shared backend other than the
1005 specified usecase to new snd devices */
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301008 /* Update the out_snd_device only before enabling the audio route */
1009 if (switch_device[usecase->id]) {
1010 usecase->out_snd_device = snd_device;
1011 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301012 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301013 use_case_table[usecase->id],
1014 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301015 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301016 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 }
1018 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 }
1020}
1021
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301022static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001023 struct audio_usecase *uc_info,
1024 snd_device_t snd_device)
1025{
1026 struct listnode *node;
1027 struct audio_usecase *usecase;
1028 bool switch_device[AUDIO_USECASE_MAX];
1029 int i, num_uc_to_switch = 0;
1030
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301031 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1032 snd_device);
1033 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001034 /*
1035 * This function is to make sure that all the active capture usecases
1036 * are always routed to the same input sound device.
1037 * For example, if audio-record and voice-call usecases are currently
1038 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1039 * is received for voice call then we have to make sure that audio-record
1040 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1041 * because of the limitation that two devices cannot be enabled
1042 * at the same time if they share the same backend.
1043 */
1044 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1045 switch_device[i] = false;
1046
1047 list_for_each(node, &adev->usecase_list) {
1048 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001049 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301051 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001052 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301053 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001054 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001055 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1057 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001058 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 switch_device[usecase->id] = true;
1061 num_uc_to_switch++;
1062 }
1063 }
1064
1065 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001066 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001067
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301068 /* Make sure the previous devices to be disabled first and then enable the
1069 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001070 list_for_each(node, &adev->usecase_list) {
1071 usecase = node_to_item(node, struct audio_usecase, list);
1072 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001073 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001074 }
1075 }
1076
1077 list_for_each(node, &adev->usecase_list) {
1078 usecase = node_to_item(node, struct audio_usecase, list);
1079 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001080 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001081 }
1082 }
1083
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 /* Re-route all the usecases on the shared backend other than the
1085 specified usecase to new snd devices */
1086 list_for_each(node, &adev->usecase_list) {
1087 usecase = node_to_item(node, struct audio_usecase, list);
1088 /* Update the in_snd_device only before enabling the audio route */
1089 if (switch_device[usecase->id] ) {
1090 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001091 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301092 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001093 }
1094 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001095 }
1096}
1097
Mingming Yin3a941d42016-02-17 18:08:05 -08001098static void reset_hdmi_sink_caps(struct stream_out *out) {
1099 int i = 0;
1100
1101 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1102 out->supported_channel_masks[i] = 0;
1103 }
1104 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1105 out->supported_formats[i] = 0;
1106 }
1107 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1108 out->supported_sample_rates[i] = 0;
1109 }
1110}
1111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001113static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114{
Mingming Yin3a941d42016-02-17 18:08:05 -08001115 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001116 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Mingming Yin3a941d42016-02-17 18:08:05 -08001118 reset_hdmi_sink_caps(out);
1119
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001120 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001121 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001122 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001123 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001124 }
1125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001128 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001129 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001130 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1131 case 6:
1132 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1133 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1134 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1135 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1136 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1137 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 break;
1139 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001140 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001141 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 break;
1143 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001144
1145 // check channel format caps
1146 i = 0;
1147 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1148 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1149 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1150 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1151 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1152 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1153 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1154 }
1155
1156 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1157 ALOGV(":%s HDMI supports DTS format", __func__);
1158 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1159 }
1160
1161 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1162 ALOGV(":%s HDMI supports DTS HD format", __func__);
1163 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1164 }
1165
1166
1167 // check sample rate caps
1168 i = 0;
1169 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1170 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1171 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1172 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1173 }
1174 }
1175
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001176 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001177}
1178
Alexy Josephb1379942016-01-29 15:49:38 -08001179audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001180 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001181{
1182 struct audio_usecase *usecase;
1183 struct listnode *node;
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001187 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001188 ALOGV("%s: usecase id %d", __func__, usecase->id);
1189 return usecase->id;
1190 }
1191 }
1192 return USECASE_INVALID;
1193}
1194
Alexy Josephb1379942016-01-29 15:49:38 -08001195struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001196 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197{
1198 struct audio_usecase *usecase;
1199 struct listnode *node;
1200
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (usecase->id == uc_id)
1204 return usecase;
1205 }
1206 return NULL;
1207}
1208
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301209/*
1210 * is a true native playback active
1211 */
1212bool audio_is_true_native_stream_active(struct audio_device *adev)
1213{
1214 bool active = false;
1215 int i = 0;
1216 struct listnode *node;
1217
1218 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1219 ALOGV("%s:napb: not in true mode or non hdphones device",
1220 __func__);
1221 active = false;
1222 goto exit;
1223 }
1224
1225 list_for_each(node, &adev->usecase_list) {
1226 struct audio_usecase *uc;
1227 uc = node_to_item(node, struct audio_usecase, list);
1228 struct stream_out *curr_out =
1229 (struct stream_out*) uc->stream.out;
1230
1231 if (curr_out && PCM_PLAYBACK == uc->type) {
1232 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1233 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1234 uc->id, curr_out->sample_rate,
1235 curr_out->bit_width,
1236 platform_get_snd_device_name(uc->out_snd_device));
1237
1238 if (is_offload_usecase(uc->id) &&
1239 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1240 active = true;
1241 ALOGD("%s:napb:native stream detected", __func__);
1242 }
1243 }
1244 }
1245exit:
1246 return active;
1247}
1248
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301249/*
1250 * if native DSD playback active
1251 */
1252bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1253{
1254 bool active = false;
1255 struct listnode *node = NULL;
1256 struct audio_usecase *uc = NULL;
1257 struct stream_out *curr_out = NULL;
1258
1259 list_for_each(node, &adev->usecase_list) {
1260 uc = node_to_item(node, struct audio_usecase, list);
1261 curr_out = (struct stream_out*) uc->stream.out;
1262
1263 if (curr_out && PCM_PLAYBACK == uc->type &&
1264 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1265 active = true;
1266 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301267 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301268 }
1269 }
1270 return active;
1271}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301272
1273static bool force_device_switch(struct audio_usecase *usecase)
1274{
1275 bool ret = false;
1276 bool is_it_true_mode = false;
1277
1278 if (is_offload_usecase(usecase->id) &&
1279 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001280 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1281 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1282 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301283 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1284 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1285 (!is_it_true_mode && adev->native_playback_enabled)){
1286 ret = true;
1287 ALOGD("napb: time to toggle native mode");
1288 }
1289 }
1290
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301291 // Force all a2dp output devices to reconfigure for proper AFE encode format
1292 if((usecase->stream.out) &&
1293 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1294 audio_extn_a2dp_is_force_device_switch()) {
1295 ALOGD("Force a2dp device switch to update new encoder config");
1296 ret = true;
1297 }
1298
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301299 return ret;
1300}
1301
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001302int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001304 snd_device_t out_snd_device = SND_DEVICE_NONE;
1305 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 struct audio_usecase *usecase = NULL;
1307 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001308 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001309 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001310 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001311 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301313 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1314
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 usecase = get_usecase_from_list(adev, uc_id);
1316 if (usecase == NULL) {
1317 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1318 return -EINVAL;
1319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001321 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001322 (usecase->type == VOIP_CALL) ||
1323 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001324 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001325 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001326 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 usecase->devices = usecase->stream.out->devices;
1328 } else {
1329 /*
1330 * If the voice call is active, use the sound devices of voice call usecase
1331 * so that it would not result any device switch. All the usecases will
1332 * be switched to new device when select_devices() is called for voice call
1333 * usecase. This is to avoid switching devices for voice call when
1334 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001335 * choose voice call device only if the use case device is
1336 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001338 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001339 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001340 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001341 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1342 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301343 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1344 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001345 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001346 in_snd_device = vc_usecase->in_snd_device;
1347 out_snd_device = vc_usecase->out_snd_device;
1348 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001349 } else if (voice_extn_compress_voip_is_active(adev)) {
1350 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001351 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001352 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1353 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001354 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001355 in_snd_device = voip_usecase->in_snd_device;
1356 out_snd_device = voip_usecase->out_snd_device;
1357 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001358 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001359 hfp_ucid = audio_extn_hfp_get_usecase();
1360 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001361 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001362 in_snd_device = hfp_usecase->in_snd_device;
1363 out_snd_device = hfp_usecase->out_snd_device;
1364 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365 }
1366 if (usecase->type == PCM_PLAYBACK) {
1367 usecase->devices = usecase->stream.out->devices;
1368 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001369 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001370 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001371 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001372 if (usecase->stream.out == adev->primary_output &&
1373 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001374 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001375 select_devices(adev, adev->active_input->usecase);
1376 }
1377 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 } else if (usecase->type == PCM_CAPTURE) {
1379 usecase->devices = usecase->stream.in->device;
1380 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001381 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001382 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001383 if (adev->active_input &&
1384 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301385 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1386 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1387 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001388 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001389 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001390 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1391 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001392 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001393 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001394 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001395 }
1396 }
1397
1398 if (out_snd_device == usecase->out_snd_device &&
1399 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301400
1401 if (!force_device_switch(usecase))
1402 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403 }
1404
sangwoobc677242013-08-08 16:53:43 +09001405 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001406 out_snd_device, platform_get_snd_device_name(out_snd_device),
1407 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409 /*
1410 * Limitation: While in call, to do a device switch we need to disable
1411 * and enable both RX and TX devices though one of them is same as current
1412 * device.
1413 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001414 if ((usecase->type == VOICE_CALL) &&
1415 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1416 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001417 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001418 }
1419
1420 if (((usecase->type == VOICE_CALL) ||
1421 (usecase->type == VOIP_CALL)) &&
1422 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1423 /* Disable sidetone only if voice/voip call already exists */
1424 if (voice_is_call_state_active(adev) ||
1425 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001426 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001427 }
1428
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429 /* Disable current sound devices */
1430 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001431 disable_audio_route(adev, usecase);
1432 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433 }
1434
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001436 disable_audio_route(adev, usecase);
1437 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 }
1439
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001440 /* Applicable only on the targets that has external modem.
1441 * New device information should be sent to modem before enabling
1442 * the devices to reduce in-call device switch time.
1443 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001444 if ((usecase->type == VOICE_CALL) &&
1445 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1446 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001447 status = platform_switch_voice_call_enable_device_config(adev->platform,
1448 out_snd_device,
1449 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001450 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001451
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452 /* Enable new sound devices */
1453 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001454 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301455 if (platform_check_codec_asrc_support(adev->platform))
1456 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001457 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 }
1459
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001460 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301461 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001463 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464
Avinash Vaish71a8b972014-07-24 15:36:33 +05301465 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001466 status = platform_switch_voice_call_device_post(adev->platform,
1467 out_snd_device,
1468 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301469 enable_audio_route_for_voice_usecases(adev, usecase);
1470 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001471
sangwoo170731f2013-06-08 15:36:36 +09001472 usecase->in_snd_device = in_snd_device;
1473 usecase->out_snd_device = out_snd_device;
1474
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301475 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001476 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301477 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001478 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301479 usecase->stream.out->flags,
1480 usecase->stream.out->format,
1481 usecase->stream.out->sample_rate,
1482 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301483 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301484 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001485 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001486
1487 /* Notify device change info to effect clients registered */
1488 audio_extn_gef_notify_device_config(
1489 usecase->stream.out->devices,
1490 usecase->stream.out->channel_mask,
1491 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301492 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001493
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001494 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001495
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001496 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1497 /* Enable sidetone only if other voice/voip call already exists */
1498 if (voice_is_call_state_active(adev) ||
1499 voice_extn_compress_voip_is_started(adev))
1500 voice_set_sidetone(adev, out_snd_device, true);
1501 }
1502
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001503 /* Applicable only on the targets that has external modem.
1504 * Enable device command should be sent to modem only after
1505 * enabling voice call mixer controls
1506 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001507 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001508 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1509 out_snd_device,
1510 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301511 ALOGD("%s: done",__func__);
1512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 return status;
1514}
1515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516static int stop_input_stream(struct stream_in *in)
1517{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301518 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 struct audio_usecase *uc_info;
1520 struct audio_device *adev = in->dev;
1521
Eric Laurentc8400632013-02-14 19:04:54 -08001522 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523
Eric Laurent994a6932013-07-17 11:51:42 -07001524 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 uc_info = get_usecase_from_list(adev, in->usecase);
1527 if (uc_info == NULL) {
1528 ALOGE("%s: Could not find the usecase (%d) in the list",
1529 __func__, in->usecase);
1530 return -EINVAL;
1531 }
1532
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001533 /* Close in-call recording streams */
1534 voice_check_and_stop_incall_rec_usecase(adev, in);
1535
Eric Laurent150dbfe2013-02-27 14:31:02 -08001536 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001537 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538
1539 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001540 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001542 list_remove(&uc_info->list);
1543 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Eric Laurent994a6932013-07-17 11:51:42 -07001545 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 return ret;
1547}
1548
1549int start_input_stream(struct stream_in *in)
1550{
1551 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001552 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 struct audio_usecase *uc_info;
1554 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301555 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Mingming Yin2664a5b2015-09-03 10:53:11 -07001557 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1558 if (get_usecase_from_list(adev, usecase) == NULL)
1559 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301560 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1561 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001562
Naresh Tanniru80659832014-06-04 18:17:56 +05301563
1564 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301565 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301566 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301567 goto error_config;
1568 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301569
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001570 /* Check if source matches incall recording usecase criteria */
1571 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1572 if (ret)
1573 goto error_config;
1574 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001575 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1576
1577 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1578 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1579 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001580 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001581 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001582
Eric Laurentb23d5282013-05-14 15:27:20 -07001583 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 if (in->pcm_device_id < 0) {
1585 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1586 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001587 ret = -EINVAL;
1588 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590
1591 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001593
1594 if (!uc_info) {
1595 ret = -ENOMEM;
1596 goto error_config;
1597 }
1598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599 uc_info->id = in->usecase;
1600 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001601 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001602 uc_info->devices = in->device;
1603 uc_info->in_snd_device = SND_DEVICE_NONE;
1604 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001606 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301607 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1608 adev->perf_lock_opts,
1609 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001610 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301612 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1613 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001614
1615 unsigned int flags = PCM_IN;
1616 unsigned int pcm_open_retry_count = 0;
1617
1618 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1619 flags |= PCM_MMAP | PCM_NOIRQ;
1620 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001621 } else if (in->realtime) {
1622 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001623 }
1624
1625 while (1) {
1626 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1627 flags, &in->config);
1628 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1629 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1630 if (in->pcm != NULL) {
1631 pcm_close(in->pcm);
1632 in->pcm = NULL;
1633 }
1634 if (pcm_open_retry_count-- == 0) {
1635 ret = -EIO;
1636 goto error_open;
1637 }
1638 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1639 continue;
1640 }
1641 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001643
1644 ALOGV("%s: pcm_prepare", __func__);
1645 ret = pcm_prepare(in->pcm);
1646 if (ret < 0) {
1647 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1648 pcm_close(in->pcm);
1649 in->pcm = NULL;
1650 goto error_open;
1651 }
1652
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001653 register_in_stream(in);
1654 if (in->realtime) {
1655 ret = pcm_start(in->pcm);
1656 if (ret < 0)
1657 goto error_open;
1658 }
1659
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301660 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001661 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001662
Eric Laurentc8400632013-02-14 19:04:54 -08001663 return ret;
1664
1665error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301666 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001668error_config:
1669 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301670 /*
1671 * sleep 50ms to allow sufficient time for kernel
1672 * drivers to recover incases like SSR.
1673 */
1674 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001676
1677 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001680void lock_input_stream(struct stream_in *in)
1681{
1682 pthread_mutex_lock(&in->pre_lock);
1683 pthread_mutex_lock(&in->lock);
1684 pthread_mutex_unlock(&in->pre_lock);
1685}
1686
1687void lock_output_stream(struct stream_out *out)
1688{
1689 pthread_mutex_lock(&out->pre_lock);
1690 pthread_mutex_lock(&out->lock);
1691 pthread_mutex_unlock(&out->pre_lock);
1692}
1693
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001694/* must be called with out->lock locked */
1695static int send_offload_cmd_l(struct stream_out* out, int command)
1696{
1697 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1698
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001699 if (!cmd) {
1700 ALOGE("failed to allocate mem for command 0x%x", command);
1701 return -ENOMEM;
1702 }
1703
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001704 ALOGVV("%s %d", __func__, command);
1705
1706 cmd->cmd = command;
1707 list_add_tail(&out->offload_cmd_list, &cmd->node);
1708 pthread_cond_signal(&out->offload_cond);
1709 return 0;
1710}
1711
1712/* must be called iwth out->lock locked */
1713static void stop_compressed_output_l(struct stream_out *out)
1714{
1715 out->offload_state = OFFLOAD_STATE_IDLE;
1716 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001717 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 if (out->compr != NULL) {
1719 compress_stop(out->compr);
1720 while (out->offload_thread_blocked) {
1721 pthread_cond_wait(&out->cond, &out->lock);
1722 }
1723 }
1724}
1725
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001726bool is_offload_usecase(audio_usecase_t uc_id)
1727{
1728 unsigned int i;
1729 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1730 if (uc_id == offload_usecases[i])
1731 return true;
1732 }
1733 return false;
1734}
1735
vivek mehta446c3962015-09-14 10:57:35 -07001736static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001737{
vivek mehta446c3962015-09-14 10:57:35 -07001738 audio_usecase_t ret_uc = USECASE_INVALID;
1739 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001740 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001741 if (!adev->multi_offload_enable) {
1742 if (is_direct_pcm)
1743 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1744 else
1745 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001746
vivek mehta446c3962015-09-14 10:57:35 -07001747 pthread_mutex_lock(&adev->lock);
1748 if (get_usecase_from_list(adev, ret_uc) != NULL)
1749 ret_uc = USECASE_INVALID;
1750 pthread_mutex_unlock(&adev->lock);
1751
1752 return ret_uc;
1753 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001754
1755 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001756 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1757 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1758 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1759 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001760 break;
1761 }
1762 }
vivek mehta446c3962015-09-14 10:57:35 -07001763
1764 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1765 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001766}
1767
1768static void free_offload_usecase(struct audio_device *adev,
1769 audio_usecase_t uc_id)
1770{
vivek mehta446c3962015-09-14 10:57:35 -07001771 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001772 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001773
1774 if (!adev->multi_offload_enable)
1775 return;
1776
1777 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1778 if (offload_usecases[offload_uc_index] == uc_id) {
1779 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001780 break;
1781 }
1782 }
1783 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1784}
1785
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786static void *offload_thread_loop(void *context)
1787{
1788 struct stream_out *out = (struct stream_out *) context;
1789 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001790 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001792 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1793 set_sched_policy(0, SP_FOREGROUND);
1794 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1795
1796 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001797 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 for (;;) {
1799 struct offload_cmd *cmd = NULL;
1800 stream_callback_event_t event;
1801 bool send_callback = false;
1802
1803 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1804 __func__, list_empty(&out->offload_cmd_list),
1805 out->offload_state);
1806 if (list_empty(&out->offload_cmd_list)) {
1807 ALOGV("%s SLEEPING", __func__);
1808 pthread_cond_wait(&out->offload_cond, &out->lock);
1809 ALOGV("%s RUNNING", __func__);
1810 continue;
1811 }
1812
1813 item = list_head(&out->offload_cmd_list);
1814 cmd = node_to_item(item, struct offload_cmd, node);
1815 list_remove(item);
1816
1817 ALOGVV("%s STATE %d CMD %d out->compr %p",
1818 __func__, out->offload_state, cmd->cmd, out->compr);
1819
1820 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1821 free(cmd);
1822 break;
1823 }
1824
1825 if (out->compr == NULL) {
1826 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001827 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001828 pthread_cond_signal(&out->cond);
1829 continue;
1830 }
1831 out->offload_thread_blocked = true;
1832 pthread_mutex_unlock(&out->lock);
1833 send_callback = false;
1834 switch(cmd->cmd) {
1835 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001836 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001838 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 send_callback = true;
1840 event = STREAM_CBK_EVENT_WRITE_READY;
1841 break;
1842 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001843 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301844 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001845 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301846 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001847 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301848 if (ret < 0)
1849 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301850 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301851 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001852 compress_drain(out->compr);
1853 else
1854 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301855 if (ret != -ENETRESET) {
1856 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301857 pthread_mutex_lock(&out->lock);
1858 out->send_new_metadata = 1;
1859 out->send_next_track_params = true;
1860 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301861 event = STREAM_CBK_EVENT_DRAIN_READY;
1862 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1863 } else
1864 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 break;
1866 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001867 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001869 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 send_callback = true;
1871 event = STREAM_CBK_EVENT_DRAIN_READY;
1872 break;
1873 default:
1874 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1875 break;
1876 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001877 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 out->offload_thread_blocked = false;
1879 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001880 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001881 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001882 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001883 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 free(cmd);
1885 }
1886
1887 pthread_cond_signal(&out->cond);
1888 while (!list_empty(&out->offload_cmd_list)) {
1889 item = list_head(&out->offload_cmd_list);
1890 list_remove(item);
1891 free(node_to_item(item, struct offload_cmd, node));
1892 }
1893 pthread_mutex_unlock(&out->lock);
1894
1895 return NULL;
1896}
1897
1898static int create_offload_callback_thread(struct stream_out *out)
1899{
1900 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1901 list_init(&out->offload_cmd_list);
1902 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1903 offload_thread_loop, out);
1904 return 0;
1905}
1906
1907static int destroy_offload_callback_thread(struct stream_out *out)
1908{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001909 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001910 stop_compressed_output_l(out);
1911 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1912
1913 pthread_mutex_unlock(&out->lock);
1914 pthread_join(out->offload_thread, (void **) NULL);
1915 pthread_cond_destroy(&out->offload_cond);
1916
1917 return 0;
1918}
1919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920static int stop_output_stream(struct stream_out *out)
1921{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301922 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 struct audio_usecase *uc_info;
1924 struct audio_device *adev = out->dev;
1925
Eric Laurent994a6932013-07-17 11:51:42 -07001926 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 uc_info = get_usecase_from_list(adev, out->usecase);
1929 if (uc_info == NULL) {
1930 ALOGE("%s: Could not find the usecase (%d) in the list",
1931 __func__, out->usecase);
1932 return -EINVAL;
1933 }
1934
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001935 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301936 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001937 if (adev->visualizer_stop_output != NULL)
1938 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001939
1940 audio_extn_dts_remove_state_notifier_node(out->usecase);
1941
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001942 if (adev->offload_effects_stop_output != NULL)
1943 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1944 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001945
Eric Laurent150dbfe2013-02-27 14:31:02 -08001946 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001947 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948
1949 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001950 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001952 list_remove(&uc_info->list);
1953 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001955 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301956 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001957 ALOGV("Disable passthrough , reset mixer to pcm");
1958 /* NO_PASSTHROUGH */
1959 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001960 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001961 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1962 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001963
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301964 /* Must be called after removing the usecase from list */
1965 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301966 audio_extn_keep_alive_start();
1967
Eric Laurent994a6932013-07-17 11:51:42 -07001968 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 return ret;
1970}
1971
1972int start_output_stream(struct stream_out *out)
1973{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 struct audio_usecase *uc_info;
1976 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301977 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001979 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1980 ret = -EINVAL;
1981 goto error_config;
1982 }
1983
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301984 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1985 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1986 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301987
Naresh Tanniru80659832014-06-04 18:17:56 +05301988 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301989 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301990 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301991 goto error_config;
1992 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301993
Eric Laurentb23d5282013-05-14 15:27:20 -07001994 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 if (out->pcm_device_id < 0) {
1996 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1997 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001998 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001999 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 }
2001
2002 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002003
2004 if (!uc_info) {
2005 ret = -ENOMEM;
2006 goto error_config;
2007 }
2008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 uc_info->id = out->usecase;
2010 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002011 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002012 uc_info->devices = out->devices;
2013 uc_info->in_snd_device = SND_DEVICE_NONE;
2014 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002015 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302017 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2018 adev->perf_lock_opts,
2019 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302020
2021 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2022 audio_extn_keep_alive_stop();
2023 if (audio_extn_passthru_is_enabled() &&
2024 audio_extn_passthru_is_passthrough_stream(out)) {
2025 audio_extn_passthru_on_start(out);
2026 audio_extn_passthru_update_stream_configuration(adev, out);
2027 }
2028 }
2029
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002030 select_devices(adev, out->usecase);
2031
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002032 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2033 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002034 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002035 unsigned int flags = PCM_OUT;
2036 unsigned int pcm_open_retry_count = 0;
2037 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2038 flags |= PCM_MMAP | PCM_NOIRQ;
2039 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002040 } else if (out->realtime) {
2041 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002042 } else
2043 flags |= PCM_MONOTONIC;
2044
2045 while (1) {
2046 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2047 flags, &out->config);
2048 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2049 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2050 if (out->pcm != NULL) {
2051 pcm_close(out->pcm);
2052 out->pcm = NULL;
2053 }
2054 if (pcm_open_retry_count-- == 0) {
2055 ret = -EIO;
2056 goto error_open;
2057 }
2058 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2059 continue;
2060 }
2061 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002063
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002064 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2065 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002066
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002067 ALOGV("%s: pcm_prepare", __func__);
2068 if (pcm_is_ready(out->pcm)) {
2069 ret = pcm_prepare(out->pcm);
2070 if (ret < 0) {
2071 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2072 pcm_close(out->pcm);
2073 out->pcm = NULL;
2074 goto error_open;
2075 }
2076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002078 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2079 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002081 out->compr = compress_open(adev->snd_card,
2082 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 COMPRESS_IN, &out->compr_config);
2084 if (out->compr && !is_compress_ready(out->compr)) {
2085 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2086 compress_close(out->compr);
2087 out->compr = NULL;
2088 ret = -EIO;
2089 goto error_open;
2090 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302091 /* compress_open sends params of the track, so reset the flag here */
2092 out->is_compr_metadata_avail = false;
2093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 if (out->offload_callback)
2095 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002096
Fred Oh3f43e742015-03-04 18:42:34 -08002097 /* Since small bufs uses blocking writes, a write will be blocked
2098 for the default max poll time (20s) in the event of an SSR.
2099 Reduce the poll time to observe and deal with SSR faster.
2100 */
Ashish Jain5106d362016-05-11 19:23:33 +05302101 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002102 compress_set_max_poll_wait(out->compr, 1000);
2103 }
2104
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002105 audio_extn_dts_create_state_notifier_node(out->usecase);
2106 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2107 popcount(out->channel_mask),
2108 out->playback_started);
2109
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002110#ifdef DS1_DOLBY_DDP_ENABLED
2111 if (audio_extn_is_dolby_format(out->format))
2112 audio_extn_dolby_send_ddp_endp_params(adev);
2113#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302114 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002115 if (adev->visualizer_start_output != NULL)
2116 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2117 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302118 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002119 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002122
2123 if (ret == 0) {
2124 register_out_stream(out);
2125 if (out->realtime) {
2126 ret = pcm_start(out->pcm);
2127 if (ret < 0)
2128 goto error_open;
2129 }
2130 }
2131
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302132 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002133 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002134
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002135 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302137 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002139error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302140 /*
2141 * sleep 50ms to allow sufficient time for kernel
2142 * drivers to recover incases like SSR.
2143 */
2144 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002145 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146}
2147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148static int check_input_parameters(uint32_t sample_rate,
2149 audio_format_t format,
2150 int channel_count)
2151{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002152 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302154 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2155 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2156 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002157 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302158 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002159
2160 switch (channel_count) {
2161 case 1:
2162 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302163 case 3:
2164 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002165 case 6:
2166 break;
2167 default:
2168 ret = -EINVAL;
2169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170
2171 switch (sample_rate) {
2172 case 8000:
2173 case 11025:
2174 case 12000:
2175 case 16000:
2176 case 22050:
2177 case 24000:
2178 case 32000:
2179 case 44100:
2180 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302181 case 96000:
2182 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 break;
2184 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002185 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 }
2187
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189}
2190
2191static size_t get_input_buffer_size(uint32_t sample_rate,
2192 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002193 int channel_count,
2194 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195{
2196 size_t size = 0;
2197
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002198 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2199 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002201 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002202 if (is_low_latency)
2203 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302204
2205 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002207 /* make sure the size is multiple of 32 bytes
2208 * At 48 kHz mono 16-bit PCM:
2209 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2210 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2211 */
2212 size += 0x1f;
2213 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002214
2215 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216}
2217
Ashish Jain058165c2016-09-28 23:18:48 +05302218static size_t get_output_period_size(uint32_t sample_rate,
2219 audio_format_t format,
2220 int channel_count,
2221 int duration /*in millisecs*/)
2222{
2223 size_t size = 0;
2224 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2225
2226 if ((duration == 0) || (sample_rate == 0) ||
2227 (bytes_per_sample == 0) || (channel_count == 0)) {
2228 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2229 bytes_per_sample, channel_count);
2230 return -EINVAL;
2231 }
2232
2233 size = (sample_rate *
2234 duration *
2235 bytes_per_sample *
2236 channel_count) / 1000;
2237 /*
2238 * To have same PCM samples for all channels, the buffer size requires to
2239 * be multiple of (number of channels * bytes per sample)
2240 * For writes to succeed, the buffer must be written at address which is multiple of 32
2241 */
2242 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2243
2244 return (size/(channel_count * bytes_per_sample));
2245}
2246
Ashish Jain5106d362016-05-11 19:23:33 +05302247static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2248{
2249 uint64_t actual_frames_rendered = 0;
2250 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2251
2252 /* This adjustment accounts for buffering after app processor.
2253 * It is based on estimated DSP latency per use case, rather than exact.
2254 */
2255 int64_t platform_latency = platform_render_latency(out->usecase) *
2256 out->sample_rate / 1000000LL;
2257
2258 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2259 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2260 * hence only estimate.
2261 */
2262 int64_t signed_frames = out->written - kernel_buffer_size;
2263
2264 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2265
2266 if (signed_frames > 0)
2267 actual_frames_rendered = signed_frames;
2268
2269 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2270 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2271 (long long int)out->written, (int)kernel_buffer_size,
2272 audio_bytes_per_sample(out->compr_config.codec->format),
2273 popcount(out->channel_mask));
2274
2275 return actual_frames_rendered;
2276}
2277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2279{
2280 struct stream_out *out = (struct stream_out *)stream;
2281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283}
2284
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002285static int out_set_sample_rate(struct audio_stream *stream __unused,
2286 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287{
2288 return -ENOSYS;
2289}
2290
2291static size_t out_get_buffer_size(const struct audio_stream *stream)
2292{
2293 struct stream_out *out = (struct stream_out *)stream;
2294
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002295 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002297 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2298 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302299 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302300 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002301
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002302 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002303 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304}
2305
2306static uint32_t out_get_channels(const struct audio_stream *stream)
2307{
2308 struct stream_out *out = (struct stream_out *)stream;
2309
2310 return out->channel_mask;
2311}
2312
2313static audio_format_t out_get_format(const struct audio_stream *stream)
2314{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 struct stream_out *out = (struct stream_out *)stream;
2316
2317 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318}
2319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002320static int out_set_format(struct audio_stream *stream __unused,
2321 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322{
2323 return -ENOSYS;
2324}
2325
2326static int out_standby(struct audio_stream *stream)
2327{
2328 struct stream_out *out = (struct stream_out *)stream;
2329 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302331 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2332 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002334 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002336 if (adev->adm_deregister_stream)
2337 adev->adm_deregister_stream(adev->adm_data, out->handle);
2338
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002339 if (is_offload_usecase(out->usecase))
2340 stop_compressed_output_l(out);
2341
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002342 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002344 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2345 voice_extn_compress_voip_close_output_stream(stream);
2346 pthread_mutex_unlock(&adev->lock);
2347 pthread_mutex_unlock(&out->lock);
2348 ALOGD("VOIP output entered standby");
2349 return 0;
2350 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 if (out->pcm) {
2352 pcm_close(out->pcm);
2353 out->pcm = NULL;
2354 }
2355 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002356 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302357 out->send_next_track_params = false;
2358 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002359 out->gapless_mdata.encoder_delay = 0;
2360 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 if (out->compr != NULL) {
2362 compress_close(out->compr);
2363 out->compr = NULL;
2364 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002365 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002367 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 }
2369 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302370 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 return 0;
2372}
2373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002374static int out_dump(const struct audio_stream *stream __unused,
2375 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376{
2377 return 0;
2378}
2379
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002380static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2381{
2382 int ret = 0;
2383 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002384
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002385 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002386 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002387 return -EINVAL;
2388 }
2389
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302390 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002391
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002392 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2393 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302394 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002395 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002396 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2397 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302398 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002399 }
2400
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002401 ALOGV("%s new encoder delay %u and padding %u", __func__,
2402 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2403
2404 return 0;
2405}
2406
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002407static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2408{
2409 return out == adev->primary_output || out == adev->voice_tx_output;
2410}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2413{
2414 struct stream_out *out = (struct stream_out *)stream;
2415 struct audio_device *adev = out->dev;
2416 struct str_parms *parms;
2417 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002418 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419
sangwoobc677242013-08-08 16:53:43 +09002420 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002421 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302423 if (!parms)
2424 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002425 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2426 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002428 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002429 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002432 * When HDMI cable is unplugged the music playback is paused and
2433 * the policy manager sends routing=0. But the audioflinger continues
2434 * to write data until standby time (3sec). As the HDMI core is
2435 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002436 * Avoid this by routing audio to speaker until standby.
2437 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002438 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2439 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302440 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002441 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2442 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002443 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302444 /*
2445 * When A2DP is disconnected the
2446 * music playback is paused and the policy manager sends routing=0
2447 * But the audioflingercontinues to write data until standby time
2448 * (3sec). As BT is turned off, the write gets blocked.
2449 * Avoid this by routing audio to speaker until standby.
2450 */
2451 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2452 (val == AUDIO_DEVICE_NONE)) {
2453 val = AUDIO_DEVICE_OUT_SPEAKER;
2454 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302455 /* To avoid a2dp to sco overlapping force route BT usecases
2456 * to speaker based on Phone state
2457 */
2458 if ((val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2459 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2460 (adev->mode == AUDIO_MODE_IN_CALL))) {
2461 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2462 val = AUDIO_DEVICE_OUT_SPEAKER;
2463 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002464 /*
2465 * select_devices() call below switches all the usecases on the same
2466 * backend to the new device. Refer to check_usecases_codec_backend() in
2467 * the select_devices(). But how do we undo this?
2468 *
2469 * For example, music playback is active on headset (deep-buffer usecase)
2470 * and if we go to ringtones and select a ringtone, low-latency usecase
2471 * will be started on headset+speaker. As we can't enable headset+speaker
2472 * and headset devices at the same time, select_devices() switches the music
2473 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2474 * So when the ringtone playback is completed, how do we undo the same?
2475 *
2476 * We are relying on the out_set_parameters() call on deep-buffer output,
2477 * once the ringtone playback is ended.
2478 * NOTE: We should not check if the current devices are same as new devices.
2479 * Because select_devices() must be called to switch back the music
2480 * playback to headset.
2481 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002482 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002483 audio_devices_t new_dev = val;
2484 bool same_dev = out->devices == new_dev;
2485 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002486
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002487 if (output_drives_call(adev, out)) {
2488 if(!voice_is_in_call(adev)) {
2489 if (adev->mode == AUDIO_MODE_IN_CALL) {
2490 adev->current_call_output = out;
2491 ret = voice_start_call(adev);
2492 }
2493 } else {
2494 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002495 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002496 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002497 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002498
2499 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002500 if (!same_dev) {
2501 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302502 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2503 adev->perf_lock_opts,
2504 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002505 if (adev->adm_on_routing_change)
2506 adev->adm_on_routing_change(adev->adm_data,
2507 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002508 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002509 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302510 if (!same_dev)
2511 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002512 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002513 }
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002518
2519 if (out == adev->primary_output) {
2520 pthread_mutex_lock(&adev->lock);
2521 audio_extn_set_parameters(adev, parms);
2522 pthread_mutex_unlock(&adev->lock);
2523 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002524 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002525 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002526 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002527
2528 audio_extn_dts_create_state_notifier_node(out->usecase);
2529 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2530 popcount(out->channel_mask),
2531 out->playback_started);
2532
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002533 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002534 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302537error:
Eric Laurent994a6932013-07-17 11:51:42 -07002538 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 return ret;
2540}
2541
2542static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2543{
2544 struct stream_out *out = (struct stream_out *)stream;
2545 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002546 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 char value[256];
2548 struct str_parms *reply = str_parms_create();
2549 size_t i, j;
2550 int ret;
2551 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002552
2553 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002554 if (reply) {
2555 str_parms_destroy(reply);
2556 }
2557 if (query) {
2558 str_parms_destroy(query);
2559 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002560 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2561 return NULL;
2562 }
2563
Eric Laurent994a6932013-07-17 11:51:42 -07002564 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2566 if (ret >= 0) {
2567 value[0] = '\0';
2568 i = 0;
2569 while (out->supported_channel_masks[i] != 0) {
2570 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2571 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2572 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002573 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002575 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 first = false;
2577 break;
2578 }
2579 }
2580 i++;
2581 }
2582 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2583 str = str_parms_to_str(reply);
2584 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002585 voice_extn_out_get_parameters(out, query, reply);
2586 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002587 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002588 free(str);
2589 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002592
Alexy Joseph62142aa2015-11-16 15:10:34 -08002593
2594 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2595 if (ret >= 0) {
2596 value[0] = '\0';
2597 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2598 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302599 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002600 } else {
2601 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302602 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002603 }
2604 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002605 if (str)
2606 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002607 str = str_parms_to_str(reply);
2608 }
2609
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002610 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2611 if (ret >= 0) {
2612 value[0] = '\0';
2613 i = 0;
2614 first = true;
2615 while (out->supported_formats[i] != 0) {
2616 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2617 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2618 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002619 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002620 }
2621 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2622 first = false;
2623 break;
2624 }
2625 }
2626 i++;
2627 }
2628 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002629 if (str)
2630 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002631 str = str_parms_to_str(reply);
2632 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002633
2634 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2635 if (ret >= 0) {
2636 value[0] = '\0';
2637 i = 0;
2638 first = true;
2639 while (out->supported_sample_rates[i] != 0) {
2640 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2641 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2642 if (!first) {
2643 strlcat(value, "|", sizeof(value));
2644 }
2645 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2646 first = false;
2647 break;
2648 }
2649 }
2650 i++;
2651 }
2652 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2653 if (str)
2654 free(str);
2655 str = str_parms_to_str(reply);
2656 }
2657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 str_parms_destroy(query);
2659 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002660 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 return str;
2662}
2663
2664static uint32_t out_get_latency(const struct audio_stream_out *stream)
2665{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002666 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002668 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669
Alexy Josephaa54c872014-12-03 02:46:47 -08002670 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002671 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002672 } else if (out->realtime) {
2673 // since the buffer won't be filled up faster than realtime,
2674 // return a smaller number
2675 if (out->config.rate)
2676 period_ms = (out->af_period_multiplier * out->config.period_size *
2677 1000) / (out->config.rate);
2678 else
2679 period_ms = 0;
2680 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002681 } else {
2682 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002684 }
2685
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302686 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002687 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688}
2689
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302690static float AmpToDb(float amplification)
2691{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302692 float db = DSD_VOLUME_MIN_DB;
2693 if (amplification > 0) {
2694 db = 20 * log10(amplification);
2695 if(db < DSD_VOLUME_MIN_DB)
2696 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302697 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302698 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302699}
2700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701static int out_set_volume(struct audio_stream_out *stream, float left,
2702 float right)
2703{
Eric Laurenta9024de2013-04-04 09:19:12 -07002704 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002705 int volume[2];
2706
Eric Laurenta9024de2013-04-04 09:19:12 -07002707 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2708 /* only take left channel into account: the API is for stereo anyway */
2709 out->muted = (left == 0.0f);
2710 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002711 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302712 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002713 /*
2714 * Set mute or umute on HDMI passthrough stream.
2715 * Only take left channel into account.
2716 * Mute is 0 and unmute 1
2717 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302718 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302719 } else if (out->format == AUDIO_FORMAT_DSD){
2720 char mixer_ctl_name[128] = "DSD Volume";
2721 struct audio_device *adev = out->dev;
2722 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2723
2724 if (!ctl) {
2725 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2726 __func__, mixer_ctl_name);
2727 return -EINVAL;
2728 }
2729 volume[0] = (int)(AmpToDb(left));
2730 volume[1] = (int)(AmpToDb(right));
2731 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2732 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002733 } else {
2734 char mixer_ctl_name[128];
2735 struct audio_device *adev = out->dev;
2736 struct mixer_ctl *ctl;
2737 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002738 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002739
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002740 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2741 "Compress Playback %d Volume", pcm_device_id);
2742 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2743 if (!ctl) {
2744 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2745 __func__, mixer_ctl_name);
2746 return -EINVAL;
2747 }
2748 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2749 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2750 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2751 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002753 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 return -ENOSYS;
2756}
2757
2758static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2759 size_t bytes)
2760{
2761 struct stream_out *out = (struct stream_out *)stream;
2762 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302763 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002764 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002766 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302767
Naresh Tanniru80659832014-06-04 18:17:56 +05302768 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002769
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302770 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302771 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302772 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2773 pthread_mutex_unlock(&out->lock);
2774 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302775 } else {
2776 /* increase written size during SSR to avoid mismatch
2777 * with the written frames count in AF
2778 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002779 // bytes per frame
2780 size_t bpf = audio_bytes_per_sample(out->format) *
2781 audio_channel_count_from_out_mask(out->channel_mask);
2782 if (bpf != 0)
2783 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302784 ALOGD(" %s: sound card is not active/SSR state", __func__);
2785 ret= -EIO;
2786 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302787 }
2788 }
2789
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302790 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302791 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2792 if (audio_bytes_per_sample(out->format) != 0)
2793 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2794 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302795 goto exit;
2796 }
2797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002799 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002800 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002801 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2802 ret = voice_extn_compress_voip_start_output_stream(out);
2803 else
2804 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002805 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002808 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 goto exit;
2810 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002811
2812 if (last_known_cal_step != -1) {
2813 ALOGD("%s: retry previous failed cal level set", __func__);
2814 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
Ashish Jain81eb2a82015-05-13 10:52:34 +05302818 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002819 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302820 adev->is_channel_status_set = true;
2821 }
2822
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002823 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002824 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002825 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002826 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002827 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2828 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302829 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2830 ALOGD("copl(%p):send next track params in gapless", out);
2831 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2832 out->send_next_track_params = false;
2833 out->is_compr_metadata_avail = false;
2834 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002835 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302836 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302837 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002838
Ashish Jain83a6cc22016-06-28 14:34:17 +05302839 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302840 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302841 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302842 pthread_mutex_unlock(&out->lock);
2843 return -EINVAL;
2844 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302845 audio_format_t dst_format = out->hal_op_format;
2846 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302847
2848 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2849 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2850
Ashish Jain83a6cc22016-06-28 14:34:17 +05302851 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302852 dst_format,
2853 buffer,
2854 src_format,
2855 frames);
2856
Ashish Jain83a6cc22016-06-28 14:34:17 +05302857 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302858 bytes_to_write);
2859
2860 /*Convert written bytes in audio flinger format*/
2861 if (ret > 0)
2862 ret = ((ret * format_to_bitwidth_table[out->format]) /
2863 format_to_bitwidth_table[dst_format]);
2864 }
2865 } else
2866 ret = compress_write(out->compr, buffer, bytes);
2867
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302868 if (ret < 0)
2869 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302870 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302871 /*msg to cb thread only if non blocking write is enabled*/
2872 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302873 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302875 } else if (-ENETRESET == ret) {
2876 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2877 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2878 pthread_mutex_unlock(&out->lock);
2879 out_standby(&out->stream.common);
2880 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 }
Ashish Jain5106d362016-05-11 19:23:33 +05302882 if ( ret == (ssize_t)bytes && !out->non_blocking)
2883 out->written += bytes;
2884
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302885 /* Call compr start only when non-zero bytes of data is there to be rendered */
2886 if (!out->playback_started && ret > 0) {
2887 int status = compress_start(out->compr);
2888 if (status < 0) {
2889 ret = status;
2890 ALOGE("%s: compr start failed with err %d", __func__, errno);
2891 goto exit;
2892 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002893 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 out->playback_started = 1;
2895 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002896
2897 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2898 popcount(out->channel_mask),
2899 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 }
2901 pthread_mutex_unlock(&out->lock);
2902 return ret;
2903 } else {
2904 if (out->pcm) {
2905 if (out->muted)
2906 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002907
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302908 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002909
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002910 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002911
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002912 if (out->config.rate)
2913 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2914 out->config.rate;
2915
2916 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2917
2918 request_out_focus(out, ns);
2919
2920 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002921 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002922 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302923 out->convert_buffer != NULL) {
2924
2925 memcpy_by_audio_format(out->convert_buffer,
2926 out->hal_op_format,
2927 buffer,
2928 out->hal_ip_format,
2929 out->config.period_size * out->config.channels);
2930
2931 ret = pcm_write(out->pcm, out->convert_buffer,
2932 (out->config.period_size *
2933 out->config.channels *
2934 format_to_bitwidth_table[out->hal_op_format]));
2935 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002936 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302937 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002938
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002939 release_out_focus(out);
2940
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302941 if (ret < 0)
2942 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302943 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2944 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2945 else
2946 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 }
2949
2950exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302951 /* ToDo: There may be a corner case when SSR happens back to back during
2952 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302953 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302954 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302955 }
2956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 pthread_mutex_unlock(&out->lock);
2958
2959 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002960 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002961 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302962 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302963 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302964 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302965 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302966 out->standby = true;
2967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302969 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2970 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2971 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 }
2973 return bytes;
2974}
2975
2976static int out_get_render_position(const struct audio_stream_out *stream,
2977 uint32_t *dsp_frames)
2978{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302980 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002981
2982 if (dsp_frames == NULL)
2983 return -EINVAL;
2984
2985 *dsp_frames = 0;
2986 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002987 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302988
2989 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2990 * this operation and adev_close_output_stream(where out gets reset).
2991 */
2992 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2993 *dsp_frames = get_actual_pcm_frames_rendered(out);
2994 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2995 return 0;
2996 }
2997
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002998 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302999 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303000 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303002 if (ret < 0)
3003 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303005 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 }
3007 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303008 if (-ENETRESET == ret) {
3009 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3010 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3011 return -EINVAL;
3012 } else if(ret < 0) {
3013 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3014 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303015 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3016 /*
3017 * Handle corner case where compress session is closed during SSR
3018 * and timestamp is queried
3019 */
3020 ALOGE(" ERROR: sound card not active, return error");
3021 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303022 } else {
3023 return 0;
3024 }
Zhou Song32a556e2015-05-05 10:46:56 +08003025 } else if (audio_is_linear_pcm(out->format)) {
3026 *dsp_frames = out->written;
3027 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003028 } else
3029 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030}
3031
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003032static int out_add_audio_effect(const struct audio_stream *stream __unused,
3033 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
3035 return 0;
3036}
3037
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003038static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3039 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040{
3041 return 0;
3042}
3043
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003044static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3045 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046{
3047 return -EINVAL;
3048}
3049
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050static int out_get_presentation_position(const struct audio_stream_out *stream,
3051 uint64_t *frames, struct timespec *timestamp)
3052{
3053 struct stream_out *out = (struct stream_out *)stream;
3054 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003055 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003056
Ashish Jain5106d362016-05-11 19:23:33 +05303057 /* below piece of code is not guarded against any lock because audioFliner serializes
3058 * this operation and adev_close_output_stream( where out gets reset).
3059 */
3060 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3061 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3062 *frames = get_actual_pcm_frames_rendered(out);
3063 /* this is the best we can do */
3064 clock_gettime(CLOCK_MONOTONIC, timestamp);
3065 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3066 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3067 return 0;
3068 }
3069
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003070 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003071
Ashish Jain5106d362016-05-11 19:23:33 +05303072 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3073 ret = compress_get_tstamp(out->compr, &dsp_frames,
3074 &out->sample_rate);
3075 ALOGVV("%s rendered frames %ld sample_rate %d",
3076 __func__, dsp_frames, out->sample_rate);
3077 *frames = dsp_frames;
3078 if (ret < 0)
3079 ret = -errno;
3080 if (-ENETRESET == ret) {
3081 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3082 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3083 ret = -EINVAL;
3084 } else
3085 ret = 0;
3086 /* this is the best we can do */
3087 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003088 } else {
3089 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003090 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003091 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3092 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003093 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003094 // This adjustment accounts for buffering after app processor.
3095 // It is based on estimated DSP latency per use case, rather than exact.
3096 signed_frames -=
3097 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3098
Eric Laurent949a0892013-09-20 09:20:13 -07003099 // It would be unusual for this value to be negative, but check just in case ...
3100 if (signed_frames >= 0) {
3101 *frames = signed_frames;
3102 ret = 0;
3103 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003104 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303105 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3106 *frames = out->written;
3107 clock_gettime(CLOCK_MONOTONIC, timestamp);
3108 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003109 }
3110 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003111 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003112 return ret;
3113}
3114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003115static int out_set_callback(struct audio_stream_out *stream,
3116 stream_callback_t callback, void *cookie)
3117{
3118 struct stream_out *out = (struct stream_out *)stream;
3119
3120 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003121 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 out->offload_callback = callback;
3123 out->offload_cookie = cookie;
3124 pthread_mutex_unlock(&out->lock);
3125 return 0;
3126}
3127
3128static int out_pause(struct audio_stream_out* stream)
3129{
3130 struct stream_out *out = (struct stream_out *)stream;
3131 int status = -ENOSYS;
3132 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003133 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003134 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003135 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303137 struct audio_device *adev = out->dev;
3138 int snd_scard_state = get_snd_card_state(adev);
3139
3140 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3141 status = compress_pause(out->compr);
3142
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003144
Mingming Yin21854652016-04-13 11:54:02 -07003145 if (audio_extn_passthru_is_active()) {
3146 ALOGV("offload use case, pause passthru");
3147 audio_extn_passthru_on_pause(out);
3148 }
3149
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303150 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003151 audio_extn_dts_notify_playback_state(out->usecase, 0,
3152 out->sample_rate, popcount(out->channel_mask),
3153 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003154 }
3155 pthread_mutex_unlock(&out->lock);
3156 }
3157 return status;
3158}
3159
3160static int out_resume(struct audio_stream_out* stream)
3161{
3162 struct stream_out *out = (struct stream_out *)stream;
3163 int status = -ENOSYS;
3164 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003165 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003166 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003168 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303170 struct audio_device *adev = out->dev;
3171 int snd_scard_state = get_snd_card_state(adev);
3172
Mingming Yin21854652016-04-13 11:54:02 -07003173 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3174 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3175 pthread_mutex_lock(&out->dev->lock);
3176 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003177 pthread_mutex_unlock(&out->dev->lock);
3178 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303179 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003180 }
3181 if (!status) {
3182 out->offload_state = OFFLOAD_STATE_PLAYING;
3183 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303184 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003185 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3186 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 }
3188 pthread_mutex_unlock(&out->lock);
3189 }
3190 return status;
3191}
3192
3193static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3194{
3195 struct stream_out *out = (struct stream_out *)stream;
3196 int status = -ENOSYS;
3197 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003198 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003199 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003200 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3201 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3202 else
3203 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3204 pthread_mutex_unlock(&out->lock);
3205 }
3206 return status;
3207}
3208
3209static int out_flush(struct audio_stream_out* stream)
3210{
3211 struct stream_out *out = (struct stream_out *)stream;
3212 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003213 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003214 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003215 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003216 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3217 stop_compressed_output_l(out);
3218 out->written = 0;
3219 } else {
3220 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3221 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003222 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003223 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 return 0;
3225 }
3226 return -ENOSYS;
3227}
3228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229/** audio_stream_in implementation **/
3230static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3231{
3232 struct stream_in *in = (struct stream_in *)stream;
3233
3234 return in->config.rate;
3235}
3236
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003237static int in_set_sample_rate(struct audio_stream *stream __unused,
3238 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239{
3240 return -ENOSYS;
3241}
3242
3243static size_t in_get_buffer_size(const struct audio_stream *stream)
3244{
3245 struct stream_in *in = (struct stream_in *)stream;
3246
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003247 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3248 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003249 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3250 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003251
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003252 return in->config.period_size * in->af_period_multiplier *
3253 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254}
3255
3256static uint32_t in_get_channels(const struct audio_stream *stream)
3257{
3258 struct stream_in *in = (struct stream_in *)stream;
3259
3260 return in->channel_mask;
3261}
3262
3263static audio_format_t in_get_format(const struct audio_stream *stream)
3264{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003265 struct stream_in *in = (struct stream_in *)stream;
3266
3267 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268}
3269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003270static int in_set_format(struct audio_stream *stream __unused,
3271 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272{
3273 return -ENOSYS;
3274}
3275
3276static int in_standby(struct audio_stream *stream)
3277{
3278 struct stream_in *in = (struct stream_in *)stream;
3279 struct audio_device *adev = in->dev;
3280 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303281 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3282 stream, in->usecase, use_case_table[in->usecase]);
3283
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003284 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003285 if (!in->standby && in->is_st_session) {
3286 ALOGD("%s: sound trigger pcm stop lab", __func__);
3287 audio_extn_sound_trigger_stop_lab(in);
3288 in->standby = 1;
3289 }
3290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003292 if (adev->adm_deregister_stream)
3293 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3294
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003295 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003297 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3298 voice_extn_compress_voip_close_input_stream(stream);
3299 ALOGD("VOIP input entered standby");
3300 } else {
3301 if (in->pcm) {
3302 pcm_close(in->pcm);
3303 in->pcm = NULL;
3304 }
3305 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003306 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003307 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 }
3309 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003310 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 return status;
3312}
3313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003314static int in_dump(const struct audio_stream *stream __unused,
3315 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return 0;
3318}
3319
3320static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3321{
3322 struct stream_in *in = (struct stream_in *)stream;
3323 struct audio_device *adev = in->dev;
3324 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003326 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303328 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 parms = str_parms_create_str(kvpairs);
3330
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303331 if (!parms)
3332 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003333 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003334 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003335
3336 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3337 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 val = atoi(value);
3339 /* no audio source uses val == 0 */
3340 if ((in->source != val) && (val != 0)) {
3341 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003342 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3343 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3344 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003345 (in->config.rate == 8000 || in->config.rate == 16000 ||
3346 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003347 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003348 err = voice_extn_compress_voip_open_input_stream(in);
3349 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003350 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003351 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003352 }
3353 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 }
3355 }
3356
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003357 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3358 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003360 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361 in->device = val;
3362 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003363 if (!in->standby && !in->is_st_session) {
3364 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003365 if (adev->adm_on_routing_change)
3366 adev->adm_on_routing_change(adev->adm_data,
3367 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003368 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003369 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 }
3371 }
3372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003374 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375
3376 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303377error:
Eric Laurent994a6932013-07-17 11:51:42 -07003378 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 return ret;
3380}
3381
3382static char* in_get_parameters(const struct audio_stream *stream,
3383 const char *keys)
3384{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003385 struct stream_in *in = (struct stream_in *)stream;
3386 struct str_parms *query = str_parms_create_str(keys);
3387 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003388 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003389
3390 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003391 if (reply) {
3392 str_parms_destroy(reply);
3393 }
3394 if (query) {
3395 str_parms_destroy(query);
3396 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003397 ALOGE("in_get_parameters: failed to create query or reply");
3398 return NULL;
3399 }
3400
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003401 ALOGV("%s: enter: keys - %s", __func__, keys);
3402
3403 voice_extn_in_get_parameters(in, query, reply);
3404
3405 str = str_parms_to_str(reply);
3406 str_parms_destroy(query);
3407 str_parms_destroy(reply);
3408
3409 ALOGV("%s: exit: returns - %s", __func__, str);
3410 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411}
3412
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003413static int in_set_gain(struct audio_stream_in *stream __unused,
3414 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415{
3416 return 0;
3417}
3418
3419static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3420 size_t bytes)
3421{
3422 struct stream_in *in = (struct stream_in *)stream;
3423 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303424 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303425 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303426 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003428 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303429
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003430 if (in->is_st_session) {
3431 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3432 /* Read from sound trigger HAL */
3433 audio_extn_sound_trigger_read(in, buffer, bytes);
3434 pthread_mutex_unlock(&in->lock);
3435 return bytes;
3436 }
3437
Ashish Jainbbce4322016-02-16 13:25:27 +05303438 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003439 ALOGD(" %s: sound card is not active/SSR state", __func__);
3440 ret= -EIO;;
3441 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303442 }
3443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003445 pthread_mutex_lock(&adev->lock);
3446 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3447 ret = voice_extn_compress_voip_start_input_stream(in);
3448 else
3449 ret = start_input_stream(in);
3450 pthread_mutex_unlock(&adev->lock);
3451 if (ret != 0) {
3452 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 }
3454 in->standby = 0;
3455 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003457 // what's the duration requested by the client?
3458 long ns = 0;
3459
3460 if (in->config.rate)
3461 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3462 in->config.rate;
3463
3464 request_in_focus(in, ns);
3465 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303468 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003469 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303470 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003471 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003472 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003473 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303474 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003475 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303476 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3477 if (bytes % 4 == 0) {
3478 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3479 int_buf_stream = buffer;
3480 for (size_t itt=0; itt < bytes/4 ; itt++) {
3481 int_buf_stream[itt] >>= 8;
3482 }
3483 } else {
3484 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3485 ret = -EINVAL;
3486 goto exit;
3487 }
3488 } if (ret < 0) {
3489 ret = -errno;
3490 }
3491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 }
3493
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003494 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 /*
3497 * Instead of writing zeroes here, we could trust the hardware
3498 * to always provide zeroes when muted.
3499 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303500 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3501 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 memset(buffer, 0, bytes);
3503
3504exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303505 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303506 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003507 if (-ENETRESET == ret)
3508 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 pthread_mutex_unlock(&in->lock);
3511
3512 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303513 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303514 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303515 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303516 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303517 in->standby = true;
3518 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303519 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003521 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303522 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303523 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 }
3525 return bytes;
3526}
3527
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003528static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529{
3530 return 0;
3531}
3532
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003533static int add_remove_audio_effect(const struct audio_stream *stream,
3534 effect_handle_t effect,
3535 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003537 struct stream_in *in = (struct stream_in *)stream;
3538 int status = 0;
3539 effect_descriptor_t desc;
3540
3541 status = (*effect)->get_descriptor(effect, &desc);
3542 if (status != 0)
3543 return status;
3544
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003545 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003546 pthread_mutex_lock(&in->dev->lock);
3547 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3548 in->enable_aec != enable &&
3549 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3550 in->enable_aec = enable;
3551 if (!in->standby)
3552 select_devices(in->dev, in->usecase);
3553 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003554 if (in->enable_ns != enable &&
3555 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3556 in->enable_ns = enable;
3557 if (!in->standby)
3558 select_devices(in->dev, in->usecase);
3559 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003560 pthread_mutex_unlock(&in->dev->lock);
3561 pthread_mutex_unlock(&in->lock);
3562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 return 0;
3564}
3565
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003566static int in_add_audio_effect(const struct audio_stream *stream,
3567 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568{
Eric Laurent994a6932013-07-17 11:51:42 -07003569 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003570 return add_remove_audio_effect(stream, effect, true);
3571}
3572
3573static int in_remove_audio_effect(const struct audio_stream *stream,
3574 effect_handle_t effect)
3575{
Eric Laurent994a6932013-07-17 11:51:42 -07003576 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003577 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578}
3579
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303580int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 audio_io_handle_t handle,
3582 audio_devices_t devices,
3583 audio_output_flags_t flags,
3584 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003585 struct audio_stream_out **stream_out,
3586 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
3588 struct audio_device *adev = (struct audio_device *)dev;
3589 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303590 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003591 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303594
3595 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3596 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003597 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303598 return -EINVAL;
3599 }
3600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3602
Mingming Yin3a941d42016-02-17 18:08:05 -08003603 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3604 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303605 devices, flags, &out->stream);
3606
3607
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003608 if (!out) {
3609 return -ENOMEM;
3610 }
3611
Haynes Mathew George204045b2015-02-25 20:32:03 -08003612 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003613 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003614 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 if (devices == AUDIO_DEVICE_NONE)
3617 devices = AUDIO_DEVICE_OUT_SPEAKER;
3618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 out->flags = flags;
3620 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003621 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003622 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003623 out->sample_rate = config->sample_rate;
3624 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3625 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003626 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003627 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003628 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303629 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630
Mingming Yin3a941d42016-02-17 18:08:05 -08003631 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3632 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3633 pthread_mutex_lock(&adev->lock);
3634 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3635 ret = read_hdmi_sink_caps(out);
3636 pthread_mutex_unlock(&adev->lock);
3637 if (ret != 0) {
3638 if (ret == -ENOSYS) {
3639 /* ignore and go with default */
3640 ret = 0;
3641 } else {
3642 ALOGE("error reading hdmi sink caps");
3643 goto error_open;
3644 }
3645 }
3646 }
3647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003649 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303650 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3651 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003652 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3653 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3654
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003655 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003656 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3657 /*
3658 * Do not handle stereo output in Multi-channel cases
3659 * Stereo case is handled in normal playback path
3660 */
3661 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3662 ret = AUDIO_CHANNEL_OUT_STEREO;
3663 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003664
3665 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3666 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003667 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003668 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003669 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003670
3671 if (config->sample_rate == 0)
3672 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3673 if (config->channel_mask == 0)
3674 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003675 if (config->format == 0)
3676 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003677
3678 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003680 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3682 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003684 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003686 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3687 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003688 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003689 ret = voice_extn_compress_voip_open_output_stream(out);
3690 if (ret != 0) {
3691 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3692 __func__, ret);
3693 goto error_open;
3694 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003695 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3696 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3697
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3699 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3700 ALOGE("%s: Unsupported Offload information", __func__);
3701 ret = -EINVAL;
3702 goto error_open;
3703 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003704
Mingming Yin3a941d42016-02-17 18:08:05 -08003705 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003706 if(config->offload_info.format == 0)
3707 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003708 if (config->offload_info.sample_rate == 0)
3709 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003710 }
3711
Mingming Yin90310102013-11-13 16:57:00 -08003712 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303713 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003714 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003715 ret = -EINVAL;
3716 goto error_open;
3717 }
3718
3719 out->compr_config.codec = (struct snd_codec *)
3720 calloc(1, sizeof(struct snd_codec));
3721
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003722 if (!out->compr_config.codec) {
3723 ret = -ENOMEM;
3724 goto error_open;
3725 }
3726
vivek mehta0ea887a2015-08-26 14:01:20 -07003727 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303728 out->stream.pause = out_pause;
3729 out->stream.flush = out_flush;
3730 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003731 out->usecase = get_offload_usecase(adev, true);
3732 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003733 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003734 out->stream.set_callback = out_set_callback;
3735 out->stream.pause = out_pause;
3736 out->stream.resume = out_resume;
3737 out->stream.drain = out_drain;
3738 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003739 out->usecase = get_offload_usecase(adev, false);
3740 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003741 }
vivek mehta446c3962015-09-14 10:57:35 -07003742
3743 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003744 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3745 config->format == 0 && config->sample_rate == 0 &&
3746 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003747 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003748 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3749 } else {
3750 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3751 ret = -EEXIST;
3752 goto error_open;
3753 }
vivek mehta446c3962015-09-14 10:57:35 -07003754 }
3755
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003756 if (config->offload_info.channel_mask)
3757 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003758 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003759 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003760 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003761 } else {
3762 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3763 ret = -EINVAL;
3764 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003765 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003766
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003767 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003768 out->sample_rate = config->offload_info.sample_rate;
3769
Mingming Yin3ee55c62014-08-04 14:23:35 -07003770 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003771
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303772 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3773 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3774 audio_extn_dolby_send_ddp_endp_params(adev);
3775 audio_extn_dolby_set_dmid(adev);
3776 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003777
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003778 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003779 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003780 out->compr_config.codec->bit_rate =
3781 config->offload_info.bit_rate;
3782 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303783 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003784 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303785 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003786 /*TODO: Do we need to change it for passthrough */
3787 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003788
Manish Dewangana6fc5442015-08-24 20:30:31 +05303789 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3790 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3791 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3792 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303793
3794 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3795 AUDIO_FORMAT_PCM) {
3796
3797 /*Based on platform support, configure appropriate alsa format for corresponding
3798 *hal input format.
3799 */
3800 out->compr_config.codec->format = hal_format_to_alsa(
3801 config->offload_info.format);
3802
Ashish Jain83a6cc22016-06-28 14:34:17 +05303803 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303804 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303805 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303806
3807 /*for direct PCM playback populate bit_width based on selected alsa format as
3808 *hal input format and alsa format might differ based on platform support.
3809 */
3810 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303811 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303812
3813 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3814
3815 /* Check if alsa session is configured with the same format as HAL input format,
3816 * if not then derive correct fragment size needed to accomodate the
3817 * conversion of HAL input format to alsa format.
3818 */
3819 audio_extn_utils_update_direct_pcm_fragment_size(out);
3820
3821 /*if hal input and output fragment size is different this indicates HAL input format is
3822 *not same as the alsa format
3823 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303824 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303825 /*Allocate a buffer to convert input data to the alsa configured format.
3826 *size of convert buffer is equal to the size required to hold one fragment size
3827 *worth of pcm data, this is because flinger does not write more than fragment_size
3828 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303829 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3830 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303831 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3832 ret = -ENOMEM;
3833 goto error_open;
3834 }
3835 }
3836 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3837 out->compr_config.fragment_size =
3838 audio_extn_passthru_get_buffer_size(&config->offload_info);
3839 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3840 } else {
3841 out->compr_config.fragment_size =
3842 platform_get_compress_offload_buffer_size(&config->offload_info);
3843 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3844 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003845
Amit Shekhar6f461b12014-08-01 14:52:58 -07003846 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303847 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003848
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003849 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3850 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003851
Alexy Josephaa54c872014-12-03 02:46:47 -08003852
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003853 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303854 out->send_next_track_params = false;
3855 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003856 out->offload_state = OFFLOAD_STATE_IDLE;
3857 out->playback_started = 0;
3858
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003859 audio_extn_dts_create_state_notifier_node(out->usecase);
3860
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003861 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3862 __func__, config->offload_info.version,
3863 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303864
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303865 /* Check if DSD audio format is supported in codec
3866 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303867 */
3868
3869 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303870 (!platform_check_codec_dsd_support(adev->platform) ||
3871 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303872 ret = -EINVAL;
3873 goto error_open;
3874 }
3875
Ashish Jain5106d362016-05-11 19:23:33 +05303876 /* Disable gapless if any of the following is true
3877 * passthrough playback
3878 * AV playback
3879 * Direct PCM playback
3880 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303881 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303882 (config->format == AUDIO_FORMAT_DSD) ||
3883 config->offload_info.has_video ||
3884 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303885 check_and_set_gapless_mode(adev, false);
3886 } else
3887 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003888
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303889 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003890 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3891 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303892 if (config->format == AUDIO_FORMAT_DSD) {
3893 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3894 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3895 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003896
3897 create_offload_callback_thread(out);
3898
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003899 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303900 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003901 if (ret != 0) {
3902 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3903 __func__, ret);
3904 goto error_open;
3905 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003906 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3907 if (config->sample_rate == 0)
3908 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3909 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3910 config->sample_rate != 8000) {
3911 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3912 ret = -EINVAL;
3913 goto error_open;
3914 }
3915 out->sample_rate = config->sample_rate;
3916 out->config.rate = config->sample_rate;
3917 if (config->format == AUDIO_FORMAT_DEFAULT)
3918 config->format = AUDIO_FORMAT_PCM_16_BIT;
3919 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3920 config->format = AUDIO_FORMAT_PCM_16_BIT;
3921 ret = -EINVAL;
3922 goto error_open;
3923 }
3924 out->format = config->format;
3925 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3926 out->config = pcm_config_afe_proxy_playback;
3927 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003928 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05303929 unsigned int channels = 0;
3930 /*Update config params to default if not set by the caller*/
3931 if (config->sample_rate == 0)
3932 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3933 if (config->channel_mask == AUDIO_CHANNEL_NONE)
3934 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3935 if (config->format == AUDIO_FORMAT_DEFAULT)
3936 config->format = AUDIO_FORMAT_PCM_16_BIT;
3937
3938 channels = audio_channel_count_from_out_mask(out->channel_mask);
3939
Ashish Jain83a6cc22016-06-28 14:34:17 +05303940 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3941 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003942 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3943 out->flags);
3944 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303945 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3946 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3947 out->config = pcm_config_low_latency;
3948 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3949 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3950 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05303951 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
3952 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
3953 if (out->config.period_size <= 0) {
3954 ALOGE("Invalid configuration period size is not valid");
3955 ret = -EINVAL;
3956 goto error_open;
3957 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05303958 } else {
3959 /* primary path is the default path selected if no other outputs are available/suitable */
3960 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3961 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3962 }
3963 out->hal_ip_format = format = out->format;
3964 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3965 out->hal_op_format = pcm_format_to_hal(out->config.format);
3966 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3967 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003968 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05303969 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303970 if (out->hal_ip_format != out->hal_op_format) {
3971 uint32_t buffer_size = out->config.period_size *
3972 format_to_bitwidth_table[out->hal_op_format] *
3973 out->config.channels;
3974 out->convert_buffer = calloc(1, buffer_size);
3975 if (out->convert_buffer == NULL){
3976 ALOGE("Allocation failed for convert buffer for size %d",
3977 out->compr_config.fragment_size);
3978 ret = -ENOMEM;
3979 goto error_open;
3980 }
3981 ALOGD("Convert buffer allocated of size %d", buffer_size);
3982 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983 }
3984
Ashish Jain83a6cc22016-06-28 14:34:17 +05303985 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3986 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3987
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003988 /* TODO remove this hardcoding and check why width is zero*/
3989 if (out->bit_width == 0)
3990 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003991 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3992 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003993 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303994 out->bit_width, out->channel_mask,
3995 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003996 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3997 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3998 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003999 if(adev->primary_output == NULL)
4000 adev->primary_output = out;
4001 else {
4002 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004003 ret = -EEXIST;
4004 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004005 }
4006 }
4007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 /* Check if this usecase is already existing */
4009 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004010 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4011 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004014 ret = -EEXIST;
4015 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 }
4017 pthread_mutex_unlock(&adev->lock);
4018
4019 out->stream.common.get_sample_rate = out_get_sample_rate;
4020 out->stream.common.set_sample_rate = out_set_sample_rate;
4021 out->stream.common.get_buffer_size = out_get_buffer_size;
4022 out->stream.common.get_channels = out_get_channels;
4023 out->stream.common.get_format = out_get_format;
4024 out->stream.common.set_format = out_set_format;
4025 out->stream.common.standby = out_standby;
4026 out->stream.common.dump = out_dump;
4027 out->stream.common.set_parameters = out_set_parameters;
4028 out->stream.common.get_parameters = out_get_parameters;
4029 out->stream.common.add_audio_effect = out_add_audio_effect;
4030 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4031 out->stream.get_latency = out_get_latency;
4032 out->stream.set_volume = out_set_volume;
4033 out->stream.write = out_write;
4034 out->stream.get_render_position = out_get_render_position;
4035 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004036 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004038 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004040 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004041 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042
4043 config->format = out->stream.common.get_format(&out->stream.common);
4044 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4045 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4046
4047 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304048 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004049 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004050
4051 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4052 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4053 popcount(out->channel_mask), out->playback_started);
4054
Eric Laurent994a6932013-07-17 11:51:42 -07004055 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004057
4058error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304059 if (out->convert_buffer)
4060 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004061 free(out);
4062 *stream_out = NULL;
4063 ALOGD("%s: exit: ret %d", __func__, ret);
4064 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065}
4066
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304067void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 struct audio_stream_out *stream)
4069{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004070 struct stream_out *out = (struct stream_out *)stream;
4071 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004072 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004073
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304074 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4075
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004076 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304077 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004078 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304079 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004080 if(ret != 0)
4081 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4082 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004083 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004084 out_standby(&stream->common);
4085
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004086 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004087 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004088 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004089 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004090 if (out->compr_config.codec != NULL)
4091 free(out->compr_config.codec);
4092 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004093
Ashish Jain83a6cc22016-06-28 14:34:17 +05304094 if (out->convert_buffer != NULL) {
4095 free(out->convert_buffer);
4096 out->convert_buffer = NULL;
4097 }
4098
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004099 if (adev->voice_tx_output == out)
4100 adev->voice_tx_output = NULL;
4101
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004102 pthread_cond_destroy(&out->cond);
4103 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004105 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106}
4107
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004108static void close_compress_sessions(struct audio_device *adev)
4109{
Mingming Yin7b762e72015-03-04 13:47:32 -08004110 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304111 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004112 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004113 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304114
4115 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004116 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304117 if (is_offload_usecase(usecase->id)) {
4118 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004119 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4120 out = usecase->stream.out;
4121 pthread_mutex_unlock(&adev->lock);
4122 out_standby(&out->stream.common);
4123 pthread_mutex_lock(&adev->lock);
4124 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304125 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004126 }
4127 pthread_mutex_unlock(&adev->lock);
4128}
4129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4131{
4132 struct audio_device *adev = (struct audio_device *)dev;
4133 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004135 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004136 int ret;
4137 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004139 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304142 if (!parms)
4143 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004144 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4145 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304146 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304147 if (strstr(snd_card_status, "OFFLINE")) {
4148 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304149 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004150 //close compress sessions on OFFLINE status
4151 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304152 } else if (strstr(snd_card_status, "ONLINE")) {
4153 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304154 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004155 //send dts hpx license if enabled
4156 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304157 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304158 }
4159
4160 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004161 status = voice_set_parameters(adev, parms);
4162 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004163 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004165 status = platform_set_parameters(adev->platform, parms);
4166 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004167 goto done;
4168
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4170 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004171 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4173 adev->bluetooth_nrec = true;
4174 else
4175 adev->bluetooth_nrec = false;
4176 }
4177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004178 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4179 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4181 adev->screen_off = false;
4182 else
4183 adev->screen_off = true;
4184 }
4185
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004186 ret = str_parms_get_int(parms, "rotation", &val);
4187 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004188 bool reverse_speakers = false;
4189 switch(val) {
4190 // FIXME: note that the code below assumes that the speakers are in the correct placement
4191 // relative to the user when the device is rotated 90deg from its default rotation. This
4192 // assumption is device-specific, not platform-specific like this code.
4193 case 270:
4194 reverse_speakers = true;
4195 break;
4196 case 0:
4197 case 90:
4198 case 180:
4199 break;
4200 default:
4201 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004202 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004203 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004204 if (status == 0) {
4205 if (adev->speaker_lr_swap != reverse_speakers) {
4206 adev->speaker_lr_swap = reverse_speakers;
4207 // only update the selected device if there is active pcm playback
4208 struct audio_usecase *usecase;
4209 struct listnode *node;
4210 list_for_each(node, &adev->usecase_list) {
4211 usecase = node_to_item(node, struct audio_usecase, list);
4212 if (usecase->type == PCM_PLAYBACK) {
4213 select_devices(adev, usecase->id);
4214 break;
4215 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004216 }
4217 }
4218 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004219 }
4220
Mingming Yin514a8bc2014-07-29 15:22:21 -07004221 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4222 if (ret >= 0) {
4223 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4224 adev->bt_wb_speech_enabled = true;
4225 else
4226 adev->bt_wb_speech_enabled = false;
4227 }
4228
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004229 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4230 if (ret >= 0) {
4231 val = atoi(value);
4232 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004233 ALOGV("cache new ext disp type and edid");
4234 ret = platform_get_ext_disp_type(adev->platform);
4235 if (ret < 0) {
4236 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004237 status = ret;
4238 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004239 }
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};