blob: 3a12adfb4ee6c9be19d4e7a767bd2ceb9f8954f9 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700230 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700231 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800233 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800234 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700236
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700237 [USECASE_VOICE2_CALL] = "voice2-call",
238 [USECASE_VOLTE_CALL] = "volte-call",
239 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800240 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800241 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
242 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800243 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700244 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
245 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
246 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800247 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
248 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
250
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700251 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
252 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700253 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
254 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700255
256 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
257 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700258 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700259};
260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261static const audio_usecase_t offload_usecases[] = {
262 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700263 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700271};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272
273#define STRING_TO_ENUM(string) { #string, string }
274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275struct string_to_enum {
276 const char *name;
277 uint32_t value;
278};
279
280static const struct string_to_enum out_channels_name_to_enum_table[] = {
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
289};
290
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700291static const struct string_to_enum out_formats_name_to_enum_table[] = {
292 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
293 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
296 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
297};
298
299//list of all supported sample rates by HDMI specification.
300static const int out_hdmi_sample_rates[] = {
301 32000, 44100, 48000, 88200, 96000, 176400, 192000,
302};
303
304static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
305 STRING_TO_ENUM(32000),
306 STRING_TO_ENUM(44100),
307 STRING_TO_ENUM(48000),
308 STRING_TO_ENUM(88200),
309 STRING_TO_ENUM(96000),
310 STRING_TO_ENUM(176400),
311 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700312};
313
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700314static struct audio_device *adev = NULL;
315static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700316static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700317//cache last MBDRC cal step level
318static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700320static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
321 int flags __unused)
322{
323 int dir = 0;
324 switch (uc_id) {
325 case USECASE_AUDIO_RECORD_LOW_LATENCY:
326 dir = 1;
327 case USECASE_AUDIO_PLAYBACK_ULL:
328 break;
329 default:
330 return false;
331 }
332
333 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
334 PCM_PLAYBACK : PCM_CAPTURE);
335 if (adev->adm_is_noirq_avail)
336 return adev->adm_is_noirq_avail(adev->adm_data,
337 adev->snd_card, dev_id, dir);
338 return false;
339}
340
341static void register_out_stream(struct stream_out *out)
342{
343 struct audio_device *adev = out->dev;
344 if (is_offload_usecase(out->usecase) ||
345 !adev->adm_register_output_stream)
346 return;
347
348 // register stream first for backward compatibility
349 adev->adm_register_output_stream(adev->adm_data,
350 out->handle,
351 out->flags);
352
353 if (!adev->adm_set_config)
354 return;
355
356 if (out->realtime)
357 adev->adm_set_config(adev->adm_data,
358 out->handle,
359 out->pcm, &out->config);
360}
361
362static void register_in_stream(struct stream_in *in)
363{
364 struct audio_device *adev = in->dev;
365 if (!adev->adm_register_input_stream)
366 return;
367
368 adev->adm_register_input_stream(adev->adm_data,
369 in->capture_handle,
370 in->flags);
371
372 if (!adev->adm_set_config)
373 return;
374
375 if (in->realtime)
376 adev->adm_set_config(adev->adm_data,
377 in->capture_handle,
378 in->pcm,
379 &in->config);
380}
381
382static void request_out_focus(struct stream_out *out, long ns)
383{
384 struct audio_device *adev = out->dev;
385
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700386 if (adev->adm_request_focus_v2)
387 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
388 else if (adev->adm_request_focus)
389 adev->adm_request_focus(adev->adm_data, out->handle);
390}
391
392static void request_in_focus(struct stream_in *in, long ns)
393{
394 struct audio_device *adev = in->dev;
395
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700396 if (adev->adm_request_focus_v2)
397 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
398 else if (adev->adm_request_focus)
399 adev->adm_request_focus(adev->adm_data, in->capture_handle);
400}
401
402static void release_out_focus(struct stream_out *out)
403{
404 struct audio_device *adev = out->dev;
405
406 if (adev->adm_abandon_focus)
407 adev->adm_abandon_focus(adev->adm_data, out->handle);
408}
409
410static void release_in_focus(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
415}
416
vivek mehtaa76401a2015-04-24 14:12:15 -0700417__attribute__ ((visibility ("default")))
418bool audio_hw_send_gain_dep_calibration(int level) {
419 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700420 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700421
422 pthread_mutex_lock(&adev_init_lock);
423
424 if (adev != NULL && adev->platform != NULL) {
425 pthread_mutex_lock(&adev->lock);
426 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700427
428 // if cal set fails, cache level info
429 // if cal set succeds, reset known last cal set
430 if (!ret_val)
431 last_known_cal_step = level;
432 else if (last_known_cal_step != -1)
433 last_known_cal_step = -1;
434
vivek mehtaa76401a2015-04-24 14:12:15 -0700435 pthread_mutex_unlock(&adev->lock);
436 } else {
437 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
438 }
439
440 pthread_mutex_unlock(&adev_init_lock);
441
442 return ret_val;
443}
444
Ashish Jain5106d362016-05-11 19:23:33 +0530445static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
446{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800447 bool gapless_enabled = false;
448 const char *mixer_ctl_name = "Compress Gapless Playback";
449 struct mixer_ctl *ctl;
450
451 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530452 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
453
454 /*Disable gapless if its AV playback*/
455 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456
457 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
458 if (!ctl) {
459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
460 __func__, mixer_ctl_name);
461 return -EINVAL;
462 }
463
464 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
465 ALOGE("%s: Could not set gapless mode %d",
466 __func__, gapless_enabled);
467 return -EINVAL;
468 }
469 return 0;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700472static bool is_supported_format(audio_format_t format)
473{
Eric Laurent86e17132013-09-12 17:49:30 -0700474 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530475 format == AUDIO_FORMAT_AAC_LC ||
476 format == AUDIO_FORMAT_AAC_HE_V1 ||
477 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530478 format == AUDIO_FORMAT_AAC_ADTS_LC ||
479 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530481 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
482 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530483 format == AUDIO_FORMAT_PCM_FLOAT ||
484 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700485 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530486 format == AUDIO_FORMAT_AC3 ||
487 format == AUDIO_FORMAT_E_AC3 ||
488 format == AUDIO_FORMAT_DTS ||
489 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800490 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530491 format == AUDIO_FORMAT_ALAC ||
492 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530493 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800495 format == AUDIO_FORMAT_WMA ||
496 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800497 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700498
499 return false;
500}
501
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700502static inline bool is_mmap_usecase(audio_usecase_t uc_id)
503{
504 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
505 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
506}
507
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508static int get_snd_codec_id(audio_format_t format)
509{
510 int id = 0;
511
Ashish Jainf9b78162014-08-25 20:36:25 +0530512 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513 case AUDIO_FORMAT_MP3:
514 id = SND_AUDIOCODEC_MP3;
515 break;
516 case AUDIO_FORMAT_AAC:
517 id = SND_AUDIOCODEC_AAC;
518 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530519 case AUDIO_FORMAT_AAC_ADTS:
520 id = SND_AUDIOCODEC_AAC;
521 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700522 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800523 id = SND_AUDIOCODEC_PCM;
524 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700525 case AUDIO_FORMAT_FLAC:
526 id = SND_AUDIOCODEC_FLAC;
527 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 case AUDIO_FORMAT_ALAC:
529 id = SND_AUDIOCODEC_ALAC;
530 break;
531 case AUDIO_FORMAT_APE:
532 id = SND_AUDIOCODEC_APE;
533 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530534 case AUDIO_FORMAT_DSD:
535 id = SND_AUDIOCODEC_DSD;
536 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530537 case AUDIO_FORMAT_VORBIS:
538 id = SND_AUDIOCODEC_VORBIS;
539 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800540 case AUDIO_FORMAT_WMA:
541 id = SND_AUDIOCODEC_WMA;
542 break;
543 case AUDIO_FORMAT_WMA_PRO:
544 id = SND_AUDIOCODEC_WMA_PRO;
545 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530546 case AUDIO_FORMAT_AC3:
547 id = SND_AUDIOCODEC_AC3;
548 break;
549 case AUDIO_FORMAT_E_AC3:
550 case AUDIO_FORMAT_E_AC3_JOC:
551 id = SND_AUDIOCODEC_EAC3;
552 break;
553 case AUDIO_FORMAT_DTS:
554 case AUDIO_FORMAT_DTS_HD:
555 id = SND_AUDIOCODEC_DTS;
556 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557 default:
Mingming Yin90310102013-11-13 16:57:00 -0800558 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700559 }
560
561 return id;
562}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800563
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530564int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530565{
566 int snd_scard_state;
567
568 if (!adev)
569 return SND_CARD_STATE_OFFLINE;
570
571 pthread_mutex_lock(&adev->snd_card_status.lock);
572 snd_scard_state = adev->snd_card_status.state;
573 pthread_mutex_unlock(&adev->snd_card_status.lock);
574
575 return snd_scard_state;
576}
577
578static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
579{
580 if (!adev)
581 return -ENOSYS;
582
583 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700584 if (adev->snd_card_status.state != snd_scard_state) {
585 adev->snd_card_status.state = snd_scard_state;
586 platform_snd_card_update(adev->platform, snd_scard_state);
587 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530588 pthread_mutex_unlock(&adev->snd_card_status.lock);
589
590 return 0;
591}
592
Avinash Vaish71a8b972014-07-24 15:36:33 +0530593static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
594 struct audio_usecase *uc_info)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598
599 if (uc_info == NULL)
600 return -EINVAL;
601
602 /* Re-route all voice usecases on the shared backend other than the
603 specified usecase to new snd devices */
604 list_for_each(node, &adev->usecase_list) {
605 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800606 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530607 enable_audio_route(adev, usecase);
608 }
609 return 0;
610}
611
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530614 ALOGV("%s", __func__);
615 audio_route_apply_and_update_path(adev->audio_route,
616 "asrc-mode");
617 adev->asrc_mode_enabled = true;
618}
619
620static void disable_asrc_mode(struct audio_device *adev)
621{
622 ALOGV("%s", __func__);
623 audio_route_reset_and_update_path(adev->audio_route,
624 "asrc-mode");
625 adev->asrc_mode_enabled = false;
626}
627
628/*
629 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
630 * 44.1 or Native DSD backends are enabled for any of current use case.
631 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
632 * - Disable current mix path use case(Headphone backend) and re-enable it with
633 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
634 * e.g. Naitve DSD or Headphone 44.1 -> + 48
635 */
636static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
637{
638 ALOGV("%s snd device %d", __func__, snd_device);
639 int new_backend_idx = platform_get_backend_index(snd_device);
640
641 if (((new_backend_idx == HEADPHONE_BACKEND) ||
642 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
643 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
644 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530645 struct listnode *node = NULL;
646 struct audio_usecase *uc = NULL;
647 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530648 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649
650 list_for_each(node, &adev->usecase_list) {
651 uc = node_to_item(node, struct audio_usecase, list);
652 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530654 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
655
656 if((new_backend_idx == HEADPHONE_BACKEND) &&
657 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
658 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530659 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
660 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 enable_asrc_mode(adev);
662 break;
663 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
664 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
665 (usecase_backend_idx == HEADPHONE_BACKEND)) {
666 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
667 __func__);
668 disable_audio_route(adev, uc);
669 disable_snd_device(adev, uc->out_snd_device);
670 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
671 if (new_backend_idx == DSD_NATIVE_BACKEND)
672 audio_route_apply_and_update_path(adev->audio_route,
673 "hph-true-highquality-mode");
674 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
675 (curr_out->bit_width >= 24))
676 audio_route_apply_and_update_path(adev->audio_route,
677 "hph-highquality-mode");
678 enable_asrc_mode(adev);
679 enable_snd_device(adev, uc->out_snd_device);
680 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530681 break;
682 }
683 }
684 }
685 }
686}
687
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700688int pcm_ioctl(struct pcm *pcm, int request, ...)
689{
690 va_list ap;
691 void * arg;
692 int pcm_fd = *(int*)pcm;
693
694 va_start(ap, request);
695 arg = va_arg(ap, void *);
696 va_end(ap);
697
698 return ioctl(pcm_fd, request, arg);
699}
700
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700701int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700705 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
707 if (usecase == NULL)
708 return -EINVAL;
709
710 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
711
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800717#ifdef DS1_DOLBY_DAP_ENABLED
718 audio_extn_dolby_set_dmid(adev);
719 audio_extn_dolby_set_endpoint(adev);
720#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700721 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700722 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530723 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700724 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530725 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800726 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700727 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700728 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 ALOGV("%s: exit", __func__);
731 return 0;
732}
733
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700734int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700738 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530740 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800741 return -EINVAL;
742
743 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 if (usecase->type == PCM_CAPTURE)
745 snd_device = usecase->in_snd_device;
746 else
747 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700752 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530753 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700758int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530761 int i, num_devices = 0;
762 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700763 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
764
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 if (snd_device < SND_DEVICE_MIN ||
766 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800767 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800768 return -EINVAL;
769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770
771 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772
773 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
774 ALOGE("%s: Invalid sound device returned", __func__);
775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700778 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 return 0;
781 }
782
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530783
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700784 if (audio_extn_spkr_prot_is_enabled())
785 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800787 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
788 audio_extn_spkr_prot_is_enabled()) {
789 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
791 return -EINVAL;
792 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200793 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800794 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800795 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200796 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800797 return -EINVAL;
798 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530799 } else if (platform_can_split_snd_device(adev->platform, snd_device,
800 &num_devices, new_snd_devices)) {
801 for (i = 0; i < num_devices; i++) {
802 enable_snd_device(adev, new_snd_devices[i]);
803 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700805 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530806
807 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
808 (audio_extn_a2dp_start_playback() < 0)) {
809 ALOGE(" fail to configure A2dp control path ");
810 return -EINVAL;
811 }
812
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700813 /* due to the possibility of calibration overwrite between listen
814 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700815 audio_extn_sound_trigger_update_device_status(snd_device,
816 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530817 audio_extn_listen_update_device_status(snd_device,
818 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700819 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700820 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700821 audio_extn_sound_trigger_update_device_status(snd_device,
822 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530823 audio_extn_listen_update_device_status(snd_device,
824 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700825 return -EINVAL;
826 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300827 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700828 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530829
830 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
831 !adev->native_playback_enabled &&
832 audio_is_true_native_stream_active(adev)) {
833 ALOGD("%s: %d: napb: enabling native mode in hardware",
834 __func__, __LINE__);
835 audio_route_apply_and_update_path(adev->audio_route,
836 "true-native-mode");
837 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840 return 0;
841}
842
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700843int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700844 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800845{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530846 int i, num_devices = 0;
847 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700848 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
849
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 if (snd_device < SND_DEVICE_MIN ||
851 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800852 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800853 return -EINVAL;
854 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
856 ALOGE("%s: device ref cnt is already 0", __func__);
857 return -EINVAL;
858 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700861
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
863 ALOGE("%s: Invalid sound device returned", __func__);
864 return -EINVAL;
865 }
866
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700868 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530869
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800870 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
871 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700872 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 } else if (platform_can_split_snd_device(adev->platform, snd_device,
874 &num_devices, new_snd_devices)) {
875 for (i = 0; i < num_devices; i++) {
876 disable_snd_device(adev, new_snd_devices[i]);
877 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300878 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700879 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300880 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700881
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530882 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
883 audio_extn_a2dp_stop_playback();
884
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700885 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530886 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530887 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
888 adev->native_playback_enabled) {
889 ALOGD("%s: %d: napb: disabling native mode in hardware",
890 __func__, __LINE__);
891 audio_route_reset_and_update_path(adev->audio_route,
892 "true-native-mode");
893 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530894 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
895 adev->asrc_mode_enabled) {
896 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530897 disable_asrc_mode(adev);
898 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530899 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530900
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200901 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700902 audio_extn_sound_trigger_update_device_status(snd_device,
903 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530904 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800905 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 return 0;
909}
910
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530912 struct audio_usecase *uc_info,
913 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914{
915 struct listnode *node;
916 struct audio_usecase *usecase;
917 bool switch_device[AUDIO_USECASE_MAX];
918 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530919 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 /*
921 * This function is to make sure that all the usecases that are active on
922 * the hardware codec backend are always routed to any one device that is
923 * handled by the hardware codec.
924 * For example, if low-latency and deep-buffer usecases are currently active
925 * on speaker and out_set_parameters(headset) is received on low-latency
926 * output, then we have to make sure deep-buffer is also switched to headset,
927 * because of the limitation that both the devices cannot be enabled
928 * at the same time as they share the same backend.
929 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700930 /*
931 * This call is to check if we need to force routing for a particular stream
932 * If there is a backend configuration change for the device when a
933 * new stream starts, then ADM needs to be closed and re-opened with the new
934 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800935 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700936 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800937 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
938 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530939 /* For a2dp device reconfigure all active sessions
940 * with new AFE encoder format based on a2dp state
941 */
942 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
943 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
944 audio_extn_a2dp_is_force_device_switch()) {
945 force_routing = true;
946 force_restart_session = true;
947 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530948 ALOGD("%s:becf: force routing %d", __func__, force_routing);
949
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800951 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800952 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 for (i = 0; i < AUDIO_USECASE_MAX; i++)
954 switch_device[i] = false;
955
956 list_for_each(node, &adev->usecase_list) {
957 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800958
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530959 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
960 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530961 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530962 platform_get_snd_device_name(usecase->out_snd_device),
963 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800964 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530965 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530966 (usecase->out_snd_device != snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530967 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
968 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +0530969 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530970 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530971 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
972
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530973 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
974 __func__, use_case_table[usecase->id],
975 platform_get_snd_device_name(usecase->out_snd_device));
976 disable_audio_route(adev, usecase);
977 switch_device[usecase->id] = true;
978 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980 }
981
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
983 num_uc_to_switch);
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700986 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530988 /* Make sure the previous devices to be disabled first and then enable the
989 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 list_for_each(node, &adev->usecase_list) {
991 usecase = node_to_item(node, struct audio_usecase, list);
992 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700993 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 }
995 }
996
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700997 list_for_each(node, &adev->usecase_list) {
998 usecase = node_to_item(node, struct audio_usecase, list);
999 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001000 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 /* Re-route all the usecases on the shared backend other than the
1005 specified usecase to new snd devices */
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301008 /* Update the out_snd_device only before enabling the audio route */
1009 if (switch_device[usecase->id]) {
1010 usecase->out_snd_device = snd_device;
1011 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301012 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301013 use_case_table[usecase->id],
1014 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301015 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301016 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 }
1018 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 }
1020}
1021
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301022static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001023 struct audio_usecase *uc_info,
1024 snd_device_t snd_device)
1025{
1026 struct listnode *node;
1027 struct audio_usecase *usecase;
1028 bool switch_device[AUDIO_USECASE_MAX];
1029 int i, num_uc_to_switch = 0;
1030
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301031 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1032 snd_device);
1033 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001034 /*
1035 * This function is to make sure that all the active capture usecases
1036 * are always routed to the same input sound device.
1037 * For example, if audio-record and voice-call usecases are currently
1038 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1039 * is received for voice call then we have to make sure that audio-record
1040 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1041 * because of the limitation that two devices cannot be enabled
1042 * at the same time if they share the same backend.
1043 */
1044 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1045 switch_device[i] = false;
1046
1047 list_for_each(node, &adev->usecase_list) {
1048 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001049 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301051 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001052 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301053 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001054 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001055 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1057 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001058 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 switch_device[usecase->id] = true;
1061 num_uc_to_switch++;
1062 }
1063 }
1064
1065 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001066 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001067
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301068 /* Make sure the previous devices to be disabled first and then enable the
1069 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001070 list_for_each(node, &adev->usecase_list) {
1071 usecase = node_to_item(node, struct audio_usecase, list);
1072 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001073 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001074 }
1075 }
1076
1077 list_for_each(node, &adev->usecase_list) {
1078 usecase = node_to_item(node, struct audio_usecase, list);
1079 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001080 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001081 }
1082 }
1083
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 /* Re-route all the usecases on the shared backend other than the
1085 specified usecase to new snd devices */
1086 list_for_each(node, &adev->usecase_list) {
1087 usecase = node_to_item(node, struct audio_usecase, list);
1088 /* Update the in_snd_device only before enabling the audio route */
1089 if (switch_device[usecase->id] ) {
1090 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001091 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301092 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001093 }
1094 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001095 }
1096}
1097
Mingming Yin3a941d42016-02-17 18:08:05 -08001098static void reset_hdmi_sink_caps(struct stream_out *out) {
1099 int i = 0;
1100
1101 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1102 out->supported_channel_masks[i] = 0;
1103 }
1104 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1105 out->supported_formats[i] = 0;
1106 }
1107 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1108 out->supported_sample_rates[i] = 0;
1109 }
1110}
1111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001113static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114{
Mingming Yin3a941d42016-02-17 18:08:05 -08001115 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001116 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Mingming Yin3a941d42016-02-17 18:08:05 -08001118 reset_hdmi_sink_caps(out);
1119
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001120 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001121 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001122 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001123 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001124 }
1125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001128 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001129 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001130 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1131 case 6:
1132 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1133 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1134 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1135 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1136 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1137 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 break;
1139 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001140 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001141 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 break;
1143 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001144
1145 // check channel format caps
1146 i = 0;
1147 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1148 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1149 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1150 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1151 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1152 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1153 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1154 }
1155
1156 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1157 ALOGV(":%s HDMI supports DTS format", __func__);
1158 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1159 }
1160
1161 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1162 ALOGV(":%s HDMI supports DTS HD format", __func__);
1163 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1164 }
1165
1166
1167 // check sample rate caps
1168 i = 0;
1169 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1170 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1171 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1172 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1173 }
1174 }
1175
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001176 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001177}
1178
Alexy Josephb1379942016-01-29 15:49:38 -08001179audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001180 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001181{
1182 struct audio_usecase *usecase;
1183 struct listnode *node;
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001187 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001188 ALOGV("%s: usecase id %d", __func__, usecase->id);
1189 return usecase->id;
1190 }
1191 }
1192 return USECASE_INVALID;
1193}
1194
Alexy Josephb1379942016-01-29 15:49:38 -08001195struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001196 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197{
1198 struct audio_usecase *usecase;
1199 struct listnode *node;
1200
1201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (usecase->id == uc_id)
1204 return usecase;
1205 }
1206 return NULL;
1207}
1208
Dhananjay Kumard4833242016-10-06 22:09:12 +05301209struct stream_in *get_next_active_input(const struct audio_device *adev)
1210{
1211 struct audio_usecase *usecase;
1212 struct listnode *node;
1213
1214 list_for_each_reverse(node, &adev->usecase_list) {
1215 usecase = node_to_item(node, struct audio_usecase, list);
1216 if (usecase->type == PCM_CAPTURE)
1217 return usecase->stream.in;
1218 }
1219 return NULL;
1220}
1221
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301222/*
1223 * is a true native playback active
1224 */
1225bool audio_is_true_native_stream_active(struct audio_device *adev)
1226{
1227 bool active = false;
1228 int i = 0;
1229 struct listnode *node;
1230
1231 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1232 ALOGV("%s:napb: not in true mode or non hdphones device",
1233 __func__);
1234 active = false;
1235 goto exit;
1236 }
1237
1238 list_for_each(node, &adev->usecase_list) {
1239 struct audio_usecase *uc;
1240 uc = node_to_item(node, struct audio_usecase, list);
1241 struct stream_out *curr_out =
1242 (struct stream_out*) uc->stream.out;
1243
1244 if (curr_out && PCM_PLAYBACK == uc->type) {
1245 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1246 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1247 uc->id, curr_out->sample_rate,
1248 curr_out->bit_width,
1249 platform_get_snd_device_name(uc->out_snd_device));
1250
1251 if (is_offload_usecase(uc->id) &&
1252 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1253 active = true;
1254 ALOGD("%s:napb:native stream detected", __func__);
1255 }
1256 }
1257 }
1258exit:
1259 return active;
1260}
1261
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301262/*
1263 * if native DSD playback active
1264 */
1265bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1266{
1267 bool active = false;
1268 struct listnode *node = NULL;
1269 struct audio_usecase *uc = NULL;
1270 struct stream_out *curr_out = NULL;
1271
1272 list_for_each(node, &adev->usecase_list) {
1273 uc = node_to_item(node, struct audio_usecase, list);
1274 curr_out = (struct stream_out*) uc->stream.out;
1275
1276 if (curr_out && PCM_PLAYBACK == uc->type &&
1277 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1278 active = true;
1279 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301280 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301281 }
1282 }
1283 return active;
1284}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301285
1286static bool force_device_switch(struct audio_usecase *usecase)
1287{
1288 bool ret = false;
1289 bool is_it_true_mode = false;
1290
1291 if (is_offload_usecase(usecase->id) &&
1292 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001293 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1294 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1295 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301296 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1297 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1298 (!is_it_true_mode && adev->native_playback_enabled)){
1299 ret = true;
1300 ALOGD("napb: time to toggle native mode");
1301 }
1302 }
1303
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301304 // Force all a2dp output devices to reconfigure for proper AFE encode format
1305 if((usecase->stream.out) &&
1306 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1307 audio_extn_a2dp_is_force_device_switch()) {
1308 ALOGD("Force a2dp device switch to update new encoder config");
1309 ret = true;
1310 }
1311
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301312 return ret;
1313}
1314
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001315int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001317 snd_device_t out_snd_device = SND_DEVICE_NONE;
1318 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 struct audio_usecase *usecase = NULL;
1320 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001321 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001322 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001323 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001324 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001325
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301326 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1327
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328 usecase = get_usecase_from_list(adev, uc_id);
1329 if (usecase == NULL) {
1330 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1331 return -EINVAL;
1332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001334 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001335 (usecase->type == VOIP_CALL) ||
1336 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001337 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001338 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001339 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340 usecase->devices = usecase->stream.out->devices;
1341 } else {
1342 /*
1343 * If the voice call is active, use the sound devices of voice call usecase
1344 * so that it would not result any device switch. All the usecases will
1345 * be switched to new device when select_devices() is called for voice call
1346 * usecase. This is to avoid switching devices for voice call when
1347 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001348 * choose voice call device only if the use case device is
1349 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001351 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001352 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001353 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001354 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1355 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301356 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1357 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001358 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 in_snd_device = vc_usecase->in_snd_device;
1360 out_snd_device = vc_usecase->out_snd_device;
1361 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001362 } else if (voice_extn_compress_voip_is_active(adev)) {
1363 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001364 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001365 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1366 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001367 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001368 in_snd_device = voip_usecase->in_snd_device;
1369 out_snd_device = voip_usecase->out_snd_device;
1370 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001371 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001372 hfp_ucid = audio_extn_hfp_get_usecase();
1373 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001374 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001375 in_snd_device = hfp_usecase->in_snd_device;
1376 out_snd_device = hfp_usecase->out_snd_device;
1377 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 }
1379 if (usecase->type == PCM_PLAYBACK) {
1380 usecase->devices = usecase->stream.out->devices;
1381 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001382 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001383 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001384 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001385 if (usecase->stream.out == adev->primary_output &&
1386 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001387 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001388 select_devices(adev, adev->active_input->usecase);
1389 }
1390 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 } else if (usecase->type == PCM_CAPTURE) {
1392 usecase->devices = usecase->stream.in->device;
1393 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001394 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001395 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001396 if (adev->active_input &&
1397 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301398 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1399 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1400 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001401 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001402 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001403 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1404 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001405 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001406 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001407 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 }
1409 }
1410
1411 if (out_snd_device == usecase->out_snd_device &&
1412 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301413
1414 if (!force_device_switch(usecase))
1415 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 }
1417
sangwoobc677242013-08-08 16:53:43 +09001418 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001419 out_snd_device, platform_get_snd_device_name(out_snd_device),
1420 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 /*
1423 * Limitation: While in call, to do a device switch we need to disable
1424 * and enable both RX and TX devices though one of them is same as current
1425 * device.
1426 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001427 if ((usecase->type == VOICE_CALL) &&
1428 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1429 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001430 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001431 }
1432
1433 if (((usecase->type == VOICE_CALL) ||
1434 (usecase->type == VOIP_CALL)) &&
1435 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1436 /* Disable sidetone only if voice/voip call already exists */
1437 if (voice_is_call_state_active(adev) ||
1438 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001439 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001440
1441 /* Disable aanc only if voice call exists */
1442 if (voice_is_call_state_active(adev))
1443 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001444 }
1445
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001446 /* Disable current sound devices */
1447 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001448 disable_audio_route(adev, usecase);
1449 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 }
1451
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001453 disable_audio_route(adev, usecase);
1454 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 }
1456
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001457 /* Applicable only on the targets that has external modem.
1458 * New device information should be sent to modem before enabling
1459 * the devices to reduce in-call device switch time.
1460 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001461 if ((usecase->type == VOICE_CALL) &&
1462 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1463 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001464 status = platform_switch_voice_call_enable_device_config(adev->platform,
1465 out_snd_device,
1466 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001467 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001468
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 /* Enable new sound devices */
1470 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001471 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301472 if (platform_check_codec_asrc_support(adev->platform))
1473 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001474 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 }
1476
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001477 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301478 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001479 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001480 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481
Avinash Vaish71a8b972014-07-24 15:36:33 +05301482 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001483 status = platform_switch_voice_call_device_post(adev->platform,
1484 out_snd_device,
1485 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301486 enable_audio_route_for_voice_usecases(adev, usecase);
1487 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001488
sangwoo170731f2013-06-08 15:36:36 +09001489 usecase->in_snd_device = in_snd_device;
1490 usecase->out_snd_device = out_snd_device;
1491
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301492 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001493 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301494 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001495 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301496 usecase->stream.out->flags,
1497 usecase->stream.out->format,
1498 usecase->stream.out->sample_rate,
1499 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301500 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301501 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001502 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001503
1504 /* Notify device change info to effect clients registered */
1505 audio_extn_gef_notify_device_config(
1506 usecase->stream.out->devices,
1507 usecase->stream.out->channel_mask,
1508 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301509 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001510
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001511 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001512
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001513 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001514 /* Enable aanc only if voice call exists */
1515 if (voice_is_call_state_active(adev))
1516 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1517
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001518 /* Enable sidetone only if other voice/voip call already exists */
1519 if (voice_is_call_state_active(adev) ||
1520 voice_extn_compress_voip_is_started(adev))
1521 voice_set_sidetone(adev, out_snd_device, true);
1522 }
1523
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001524 /* Applicable only on the targets that has external modem.
1525 * Enable device command should be sent to modem only after
1526 * enabling voice call mixer controls
1527 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001528 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001529 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1530 out_snd_device,
1531 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301532 ALOGD("%s: done",__func__);
1533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 return status;
1535}
1536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537static int stop_input_stream(struct stream_in *in)
1538{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301539 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 struct audio_usecase *uc_info;
1541 struct audio_device *adev = in->dev;
1542
Dhananjay Kumard4833242016-10-06 22:09:12 +05301543 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Eric Laurent994a6932013-07-17 11:51:42 -07001545 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 uc_info = get_usecase_from_list(adev, in->usecase);
1548 if (uc_info == NULL) {
1549 ALOGE("%s: Could not find the usecase (%d) in the list",
1550 __func__, in->usecase);
1551 return -EINVAL;
1552 }
1553
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001554 /* Close in-call recording streams */
1555 voice_check_and_stop_incall_rec_usecase(adev, in);
1556
Eric Laurent150dbfe2013-02-27 14:31:02 -08001557 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001558 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559
1560 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001561 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001563 list_remove(&uc_info->list);
1564 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565
Eric Laurent994a6932013-07-17 11:51:42 -07001566 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 return ret;
1568}
1569
1570int start_input_stream(struct stream_in *in)
1571{
1572 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001573 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574 struct audio_usecase *uc_info;
1575 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301576 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577
Mingming Yin2664a5b2015-09-03 10:53:11 -07001578 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1579 if (get_usecase_from_list(adev, usecase) == NULL)
1580 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301581 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1582 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001583
Naresh Tanniru80659832014-06-04 18:17:56 +05301584
1585 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301586 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301587 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301588 goto error_config;
1589 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301590
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001591 /* Check if source matches incall recording usecase criteria */
1592 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1593 if (ret)
1594 goto error_config;
1595 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001596 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1597
1598 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1599 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1600 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001601 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001602 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001603
Eric Laurentb23d5282013-05-14 15:27:20 -07001604 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 if (in->pcm_device_id < 0) {
1606 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1607 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001608 ret = -EINVAL;
1609 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611
1612 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001614
1615 if (!uc_info) {
1616 ret = -ENOMEM;
1617 goto error_config;
1618 }
1619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 uc_info->id = in->usecase;
1621 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001622 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001623 uc_info->devices = in->device;
1624 uc_info->in_snd_device = SND_DEVICE_NONE;
1625 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001627 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301628 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1629 adev->perf_lock_opts,
1630 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001631 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301633 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1634 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001635
1636 unsigned int flags = PCM_IN;
1637 unsigned int pcm_open_retry_count = 0;
1638
1639 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1640 flags |= PCM_MMAP | PCM_NOIRQ;
1641 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001642 } else if (in->realtime) {
1643 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001644 }
1645
1646 while (1) {
1647 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1648 flags, &in->config);
1649 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1650 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1651 if (in->pcm != NULL) {
1652 pcm_close(in->pcm);
1653 in->pcm = NULL;
1654 }
1655 if (pcm_open_retry_count-- == 0) {
1656 ret = -EIO;
1657 goto error_open;
1658 }
1659 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1660 continue;
1661 }
1662 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001664
1665 ALOGV("%s: pcm_prepare", __func__);
1666 ret = pcm_prepare(in->pcm);
1667 if (ret < 0) {
1668 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1669 pcm_close(in->pcm);
1670 in->pcm = NULL;
1671 goto error_open;
1672 }
1673
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001674 register_in_stream(in);
1675 if (in->realtime) {
1676 ret = pcm_start(in->pcm);
1677 if (ret < 0)
1678 goto error_open;
1679 }
1680
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301681 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001682 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001683
Eric Laurentc8400632013-02-14 19:04:54 -08001684 return ret;
1685
1686error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301687 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001689error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301690 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301691 /*
1692 * sleep 50ms to allow sufficient time for kernel
1693 * drivers to recover incases like SSR.
1694 */
1695 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001696 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001697
1698 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699}
1700
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001701void lock_input_stream(struct stream_in *in)
1702{
1703 pthread_mutex_lock(&in->pre_lock);
1704 pthread_mutex_lock(&in->lock);
1705 pthread_mutex_unlock(&in->pre_lock);
1706}
1707
1708void lock_output_stream(struct stream_out *out)
1709{
1710 pthread_mutex_lock(&out->pre_lock);
1711 pthread_mutex_lock(&out->lock);
1712 pthread_mutex_unlock(&out->pre_lock);
1713}
1714
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715/* must be called with out->lock locked */
1716static int send_offload_cmd_l(struct stream_out* out, int command)
1717{
1718 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1719
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001720 if (!cmd) {
1721 ALOGE("failed to allocate mem for command 0x%x", command);
1722 return -ENOMEM;
1723 }
1724
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 ALOGVV("%s %d", __func__, command);
1726
1727 cmd->cmd = command;
1728 list_add_tail(&out->offload_cmd_list, &cmd->node);
1729 pthread_cond_signal(&out->offload_cond);
1730 return 0;
1731}
1732
1733/* must be called iwth out->lock locked */
1734static void stop_compressed_output_l(struct stream_out *out)
1735{
1736 out->offload_state = OFFLOAD_STATE_IDLE;
1737 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001738 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 if (out->compr != NULL) {
1740 compress_stop(out->compr);
1741 while (out->offload_thread_blocked) {
1742 pthread_cond_wait(&out->cond, &out->lock);
1743 }
1744 }
1745}
1746
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001747bool is_offload_usecase(audio_usecase_t uc_id)
1748{
1749 unsigned int i;
1750 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1751 if (uc_id == offload_usecases[i])
1752 return true;
1753 }
1754 return false;
1755}
1756
vivek mehta446c3962015-09-14 10:57:35 -07001757static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001758{
vivek mehta446c3962015-09-14 10:57:35 -07001759 audio_usecase_t ret_uc = USECASE_INVALID;
1760 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001761 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001762 if (!adev->multi_offload_enable) {
1763 if (is_direct_pcm)
1764 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1765 else
1766 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001767
vivek mehta446c3962015-09-14 10:57:35 -07001768 pthread_mutex_lock(&adev->lock);
1769 if (get_usecase_from_list(adev, ret_uc) != NULL)
1770 ret_uc = USECASE_INVALID;
1771 pthread_mutex_unlock(&adev->lock);
1772
1773 return ret_uc;
1774 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001775
1776 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001777 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1778 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1779 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1780 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001781 break;
1782 }
1783 }
vivek mehta446c3962015-09-14 10:57:35 -07001784
1785 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1786 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001787}
1788
1789static void free_offload_usecase(struct audio_device *adev,
1790 audio_usecase_t uc_id)
1791{
vivek mehta446c3962015-09-14 10:57:35 -07001792 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001793 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001794
1795 if (!adev->multi_offload_enable)
1796 return;
1797
1798 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1799 if (offload_usecases[offload_uc_index] == uc_id) {
1800 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001801 break;
1802 }
1803 }
1804 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1805}
1806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807static void *offload_thread_loop(void *context)
1808{
1809 struct stream_out *out = (struct stream_out *) context;
1810 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001811 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001813 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1814 set_sched_policy(0, SP_FOREGROUND);
1815 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1816
1817 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001818 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 for (;;) {
1820 struct offload_cmd *cmd = NULL;
1821 stream_callback_event_t event;
1822 bool send_callback = false;
1823
1824 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1825 __func__, list_empty(&out->offload_cmd_list),
1826 out->offload_state);
1827 if (list_empty(&out->offload_cmd_list)) {
1828 ALOGV("%s SLEEPING", __func__);
1829 pthread_cond_wait(&out->offload_cond, &out->lock);
1830 ALOGV("%s RUNNING", __func__);
1831 continue;
1832 }
1833
1834 item = list_head(&out->offload_cmd_list);
1835 cmd = node_to_item(item, struct offload_cmd, node);
1836 list_remove(item);
1837
1838 ALOGVV("%s STATE %d CMD %d out->compr %p",
1839 __func__, out->offload_state, cmd->cmd, out->compr);
1840
1841 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1842 free(cmd);
1843 break;
1844 }
1845
1846 if (out->compr == NULL) {
1847 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001848 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001849 pthread_cond_signal(&out->cond);
1850 continue;
1851 }
1852 out->offload_thread_blocked = true;
1853 pthread_mutex_unlock(&out->lock);
1854 send_callback = false;
1855 switch(cmd->cmd) {
1856 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001857 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001859 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001860 send_callback = true;
1861 event = STREAM_CBK_EVENT_WRITE_READY;
1862 break;
1863 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001864 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301865 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001866 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301867 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001868 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301869 if (ret < 0)
1870 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301871 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301872 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001873 compress_drain(out->compr);
1874 else
1875 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301876 if (ret != -ENETRESET) {
1877 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301878 pthread_mutex_lock(&out->lock);
1879 out->send_new_metadata = 1;
1880 out->send_next_track_params = true;
1881 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301882 event = STREAM_CBK_EVENT_DRAIN_READY;
1883 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1884 } else
1885 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001886 break;
1887 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001888 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001889 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001890 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001891 send_callback = true;
1892 event = STREAM_CBK_EVENT_DRAIN_READY;
1893 break;
1894 default:
1895 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1896 break;
1897 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001898 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001899 out->offload_thread_blocked = false;
1900 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001901 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001902 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001903 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001904 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001905 free(cmd);
1906 }
1907
1908 pthread_cond_signal(&out->cond);
1909 while (!list_empty(&out->offload_cmd_list)) {
1910 item = list_head(&out->offload_cmd_list);
1911 list_remove(item);
1912 free(node_to_item(item, struct offload_cmd, node));
1913 }
1914 pthread_mutex_unlock(&out->lock);
1915
1916 return NULL;
1917}
1918
1919static int create_offload_callback_thread(struct stream_out *out)
1920{
1921 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1922 list_init(&out->offload_cmd_list);
1923 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1924 offload_thread_loop, out);
1925 return 0;
1926}
1927
1928static int destroy_offload_callback_thread(struct stream_out *out)
1929{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001930 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 stop_compressed_output_l(out);
1932 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1933
1934 pthread_mutex_unlock(&out->lock);
1935 pthread_join(out->offload_thread, (void **) NULL);
1936 pthread_cond_destroy(&out->offload_cond);
1937
1938 return 0;
1939}
1940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941static int stop_output_stream(struct stream_out *out)
1942{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301943 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 struct audio_usecase *uc_info;
1945 struct audio_device *adev = out->dev;
1946
Eric Laurent994a6932013-07-17 11:51:42 -07001947 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 uc_info = get_usecase_from_list(adev, out->usecase);
1950 if (uc_info == NULL) {
1951 ALOGE("%s: Could not find the usecase (%d) in the list",
1952 __func__, out->usecase);
1953 return -EINVAL;
1954 }
1955
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001956 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301957 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001958 if (adev->visualizer_stop_output != NULL)
1959 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001960
1961 audio_extn_dts_remove_state_notifier_node(out->usecase);
1962
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001963 if (adev->offload_effects_stop_output != NULL)
1964 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1965 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001966
Eric Laurent150dbfe2013-02-27 14:31:02 -08001967 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001968 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001969
1970 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001971 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001973 list_remove(&uc_info->list);
1974 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001976 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301977 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001978 ALOGV("Disable passthrough , reset mixer to pcm");
1979 /* NO_PASSTHROUGH */
1980 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001981 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001982 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1983 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001984
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301985 /* Must be called after removing the usecase from list */
1986 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301987 audio_extn_keep_alive_start();
1988
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 return ret;
1991}
1992
1993int start_output_stream(struct stream_out *out)
1994{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 struct audio_usecase *uc_info;
1997 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301998 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002000 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2001 ret = -EINVAL;
2002 goto error_config;
2003 }
2004
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302005 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2006 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2007 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302008
Naresh Tanniru80659832014-06-04 18:17:56 +05302009 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302010 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302011 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302012 goto error_config;
2013 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302014
Eric Laurentb23d5282013-05-14 15:27:20 -07002015 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 if (out->pcm_device_id < 0) {
2017 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2018 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002019 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002020 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021 }
2022
2023 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002024
2025 if (!uc_info) {
2026 ret = -ENOMEM;
2027 goto error_config;
2028 }
2029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 uc_info->id = out->usecase;
2031 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002032 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002033 uc_info->devices = out->devices;
2034 uc_info->in_snd_device = SND_DEVICE_NONE;
2035 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002036 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302038 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2039 adev->perf_lock_opts,
2040 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302041
2042 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2043 audio_extn_keep_alive_stop();
2044 if (audio_extn_passthru_is_enabled() &&
2045 audio_extn_passthru_is_passthrough_stream(out)) {
2046 audio_extn_passthru_on_start(out);
2047 audio_extn_passthru_update_stream_configuration(adev, out);
2048 }
2049 }
2050
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002051 select_devices(adev, out->usecase);
2052
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002053 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2054 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002055 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002056 unsigned int flags = PCM_OUT;
2057 unsigned int pcm_open_retry_count = 0;
2058 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2059 flags |= PCM_MMAP | PCM_NOIRQ;
2060 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002061 } else if (out->realtime) {
2062 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002063 } else
2064 flags |= PCM_MONOTONIC;
2065
2066 while (1) {
2067 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2068 flags, &out->config);
2069 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2070 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2071 if (out->pcm != NULL) {
2072 pcm_close(out->pcm);
2073 out->pcm = NULL;
2074 }
2075 if (pcm_open_retry_count-- == 0) {
2076 ret = -EIO;
2077 goto error_open;
2078 }
2079 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2080 continue;
2081 }
2082 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002084
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002085 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2086 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002087
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002088 ALOGV("%s: pcm_prepare", __func__);
2089 if (pcm_is_ready(out->pcm)) {
2090 ret = pcm_prepare(out->pcm);
2091 if (ret < 0) {
2092 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2093 pcm_close(out->pcm);
2094 out->pcm = NULL;
2095 goto error_open;
2096 }
2097 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002099 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2100 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002102 out->compr = compress_open(adev->snd_card,
2103 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104 COMPRESS_IN, &out->compr_config);
2105 if (out->compr && !is_compress_ready(out->compr)) {
2106 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2107 compress_close(out->compr);
2108 out->compr = NULL;
2109 ret = -EIO;
2110 goto error_open;
2111 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302112 /* compress_open sends params of the track, so reset the flag here */
2113 out->is_compr_metadata_avail = false;
2114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 if (out->offload_callback)
2116 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002117
Fred Oh3f43e742015-03-04 18:42:34 -08002118 /* Since small bufs uses blocking writes, a write will be blocked
2119 for the default max poll time (20s) in the event of an SSR.
2120 Reduce the poll time to observe and deal with SSR faster.
2121 */
Ashish Jain5106d362016-05-11 19:23:33 +05302122 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002123 compress_set_max_poll_wait(out->compr, 1000);
2124 }
2125
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002126 audio_extn_dts_create_state_notifier_node(out->usecase);
2127 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2128 popcount(out->channel_mask),
2129 out->playback_started);
2130
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002131#ifdef DS1_DOLBY_DDP_ENABLED
2132 if (audio_extn_is_dolby_format(out->format))
2133 audio_extn_dolby_send_ddp_endp_params(adev);
2134#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302135 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002136 if (adev->visualizer_start_output != NULL)
2137 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2138 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302139 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002140 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002143
2144 if (ret == 0) {
2145 register_out_stream(out);
2146 if (out->realtime) {
2147 ret = pcm_start(out->pcm);
2148 if (ret < 0)
2149 goto error_open;
2150 }
2151 }
2152
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302153 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002154 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002155
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002156 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302158 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002160error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302161 /*
2162 * sleep 50ms to allow sufficient time for kernel
2163 * drivers to recover incases like SSR.
2164 */
2165 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002166 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167}
2168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169static int check_input_parameters(uint32_t sample_rate,
2170 audio_format_t format,
2171 int channel_count)
2172{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002173 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302175 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2176 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2177 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002178 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302179 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002180
2181 switch (channel_count) {
2182 case 1:
2183 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302184 case 3:
2185 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002186 case 6:
2187 break;
2188 default:
2189 ret = -EINVAL;
2190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191
2192 switch (sample_rate) {
2193 case 8000:
2194 case 11025:
2195 case 12000:
2196 case 16000:
2197 case 22050:
2198 case 24000:
2199 case 32000:
2200 case 44100:
2201 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302202 case 96000:
2203 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 break;
2205 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002206 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 }
2208
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002209 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210}
2211
2212static size_t get_input_buffer_size(uint32_t sample_rate,
2213 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002214 int channel_count,
2215 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216{
2217 size_t size = 0;
2218
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002219 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2220 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002222 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002223 if (is_low_latency)
2224 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302225
2226 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002228 /* make sure the size is multiple of 32 bytes
2229 * At 48 kHz mono 16-bit PCM:
2230 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2231 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2232 */
2233 size += 0x1f;
2234 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002235
2236 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237}
2238
Ashish Jain058165c2016-09-28 23:18:48 +05302239static size_t get_output_period_size(uint32_t sample_rate,
2240 audio_format_t format,
2241 int channel_count,
2242 int duration /*in millisecs*/)
2243{
2244 size_t size = 0;
2245 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2246
2247 if ((duration == 0) || (sample_rate == 0) ||
2248 (bytes_per_sample == 0) || (channel_count == 0)) {
2249 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2250 bytes_per_sample, channel_count);
2251 return -EINVAL;
2252 }
2253
2254 size = (sample_rate *
2255 duration *
2256 bytes_per_sample *
2257 channel_count) / 1000;
2258 /*
2259 * To have same PCM samples for all channels, the buffer size requires to
2260 * be multiple of (number of channels * bytes per sample)
2261 * For writes to succeed, the buffer must be written at address which is multiple of 32
2262 */
2263 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2264
2265 return (size/(channel_count * bytes_per_sample));
2266}
2267
Ashish Jain5106d362016-05-11 19:23:33 +05302268static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2269{
2270 uint64_t actual_frames_rendered = 0;
2271 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2272
2273 /* This adjustment accounts for buffering after app processor.
2274 * It is based on estimated DSP latency per use case, rather than exact.
2275 */
2276 int64_t platform_latency = platform_render_latency(out->usecase) *
2277 out->sample_rate / 1000000LL;
2278
2279 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2280 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2281 * hence only estimate.
2282 */
2283 int64_t signed_frames = out->written - kernel_buffer_size;
2284
2285 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2286
2287 if (signed_frames > 0)
2288 actual_frames_rendered = signed_frames;
2289
2290 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2291 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2292 (long long int)out->written, (int)kernel_buffer_size,
2293 audio_bytes_per_sample(out->compr_config.codec->format),
2294 popcount(out->channel_mask));
2295
2296 return actual_frames_rendered;
2297}
2298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2300{
2301 struct stream_out *out = (struct stream_out *)stream;
2302
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002303 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304}
2305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002306static int out_set_sample_rate(struct audio_stream *stream __unused,
2307 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308{
2309 return -ENOSYS;
2310}
2311
2312static size_t out_get_buffer_size(const struct audio_stream *stream)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002316 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002318 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2319 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302320 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302321 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002322
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002323 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002324 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325}
2326
2327static uint32_t out_get_channels(const struct audio_stream *stream)
2328{
2329 struct stream_out *out = (struct stream_out *)stream;
2330
2331 return out->channel_mask;
2332}
2333
2334static audio_format_t out_get_format(const struct audio_stream *stream)
2335{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 struct stream_out *out = (struct stream_out *)stream;
2337
2338 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339}
2340
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002341static int out_set_format(struct audio_stream *stream __unused,
2342 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343{
2344 return -ENOSYS;
2345}
2346
2347static int out_standby(struct audio_stream *stream)
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302352 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2353 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002355 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002357 if (adev->adm_deregister_stream)
2358 adev->adm_deregister_stream(adev->adm_data, out->handle);
2359
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002360 if (is_offload_usecase(out->usecase))
2361 stop_compressed_output_l(out);
2362
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002363 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002365 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2366 voice_extn_compress_voip_close_output_stream(stream);
2367 pthread_mutex_unlock(&adev->lock);
2368 pthread_mutex_unlock(&out->lock);
2369 ALOGD("VOIP output entered standby");
2370 return 0;
2371 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 if (out->pcm) {
2373 pcm_close(out->pcm);
2374 out->pcm = NULL;
2375 }
2376 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002377 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302378 out->send_next_track_params = false;
2379 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002380 out->gapless_mdata.encoder_delay = 0;
2381 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002382 if (out->compr != NULL) {
2383 compress_close(out->compr);
2384 out->compr = NULL;
2385 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002386 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002388 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 }
2390 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302391 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 return 0;
2393}
2394
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002395static int out_dump(const struct audio_stream *stream __unused,
2396 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397{
2398 return 0;
2399}
2400
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002401static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2402{
2403 int ret = 0;
2404 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002405
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002406 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002407 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002408 return -EINVAL;
2409 }
2410
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302411 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002412
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002413 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2414 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302415 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002416 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002417 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2418 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302419 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002420 }
2421
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002422 ALOGV("%s new encoder delay %u and padding %u", __func__,
2423 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2424
2425 return 0;
2426}
2427
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002428static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2429{
2430 return out == adev->primary_output || out == adev->voice_tx_output;
2431}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 struct audio_device *adev = out->dev;
2437 struct str_parms *parms;
2438 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002439 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440
sangwoobc677242013-08-08 16:53:43 +09002441 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002442 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302444 if (!parms)
2445 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002446 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2447 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002449 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002450 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002452 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002453 * When HDMI cable is unplugged the music playback is paused and
2454 * the policy manager sends routing=0. But the audioflinger continues
2455 * to write data until standby time (3sec). As the HDMI core is
2456 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002457 * Avoid this by routing audio to speaker until standby.
2458 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002459 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2460 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302461 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002462 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2463 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002464 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302465 /*
2466 * When A2DP is disconnected the
2467 * music playback is paused and the policy manager sends routing=0
2468 * But the audioflingercontinues to write data until standby time
2469 * (3sec). As BT is turned off, the write gets blocked.
2470 * Avoid this by routing audio to speaker until standby.
2471 */
2472 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2473 (val == AUDIO_DEVICE_NONE)) {
2474 val = AUDIO_DEVICE_OUT_SPEAKER;
2475 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302476 /* To avoid a2dp to sco overlapping force route BT usecases
2477 * to speaker based on Phone state
2478 */
2479 if ((val & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2480 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2481 (adev->mode == AUDIO_MODE_IN_CALL))) {
2482 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2483 val = AUDIO_DEVICE_OUT_SPEAKER;
2484 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002485 /*
2486 * select_devices() call below switches all the usecases on the same
2487 * backend to the new device. Refer to check_usecases_codec_backend() in
2488 * the select_devices(). But how do we undo this?
2489 *
2490 * For example, music playback is active on headset (deep-buffer usecase)
2491 * and if we go to ringtones and select a ringtone, low-latency usecase
2492 * will be started on headset+speaker. As we can't enable headset+speaker
2493 * and headset devices at the same time, select_devices() switches the music
2494 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2495 * So when the ringtone playback is completed, how do we undo the same?
2496 *
2497 * We are relying on the out_set_parameters() call on deep-buffer output,
2498 * once the ringtone playback is ended.
2499 * NOTE: We should not check if the current devices are same as new devices.
2500 * Because select_devices() must be called to switch back the music
2501 * playback to headset.
2502 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002503 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002504 audio_devices_t new_dev = val;
2505 bool same_dev = out->devices == new_dev;
2506 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002507
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002508 if (output_drives_call(adev, out)) {
2509 if(!voice_is_in_call(adev)) {
2510 if (adev->mode == AUDIO_MODE_IN_CALL) {
2511 adev->current_call_output = out;
2512 ret = voice_start_call(adev);
2513 }
2514 } else {
2515 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002516 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002517 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002518 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002519
2520 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002521 if (!same_dev) {
2522 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302523 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2524 adev->perf_lock_opts,
2525 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002526 if (adev->adm_on_routing_change)
2527 adev->adm_on_routing_change(adev->adm_data,
2528 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002529 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002530 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302531 if (!same_dev)
2532 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002533 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002534 }
2535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002539
2540 if (out == adev->primary_output) {
2541 pthread_mutex_lock(&adev->lock);
2542 audio_extn_set_parameters(adev, parms);
2543 pthread_mutex_unlock(&adev->lock);
2544 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002545 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002546 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002547 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002548
2549 audio_extn_dts_create_state_notifier_node(out->usecase);
2550 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2551 popcount(out->channel_mask),
2552 out->playback_started);
2553
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002554 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002555 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302558error:
Eric Laurent994a6932013-07-17 11:51:42 -07002559 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 return ret;
2561}
2562
2563static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002567 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 char value[256];
2569 struct str_parms *reply = str_parms_create();
2570 size_t i, j;
2571 int ret;
2572 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002573
2574 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002575 if (reply) {
2576 str_parms_destroy(reply);
2577 }
2578 if (query) {
2579 str_parms_destroy(query);
2580 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002581 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2582 return NULL;
2583 }
2584
Eric Laurent994a6932013-07-17 11:51:42 -07002585 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2587 if (ret >= 0) {
2588 value[0] = '\0';
2589 i = 0;
2590 while (out->supported_channel_masks[i] != 0) {
2591 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2592 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2593 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002594 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002596 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 first = false;
2598 break;
2599 }
2600 }
2601 i++;
2602 }
2603 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2604 str = str_parms_to_str(reply);
2605 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002606 voice_extn_out_get_parameters(out, query, reply);
2607 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002608 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002609 free(str);
2610 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002613
Alexy Joseph62142aa2015-11-16 15:10:34 -08002614
2615 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2616 if (ret >= 0) {
2617 value[0] = '\0';
2618 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2619 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302620 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002621 } else {
2622 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302623 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002624 }
2625 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002626 if (str)
2627 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002628 str = str_parms_to_str(reply);
2629 }
2630
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002631 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2632 if (ret >= 0) {
2633 value[0] = '\0';
2634 i = 0;
2635 first = true;
2636 while (out->supported_formats[i] != 0) {
2637 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2638 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2639 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002640 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002641 }
2642 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2643 first = false;
2644 break;
2645 }
2646 }
2647 i++;
2648 }
2649 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002650 if (str)
2651 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002652 str = str_parms_to_str(reply);
2653 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002654
2655 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2656 if (ret >= 0) {
2657 value[0] = '\0';
2658 i = 0;
2659 first = true;
2660 while (out->supported_sample_rates[i] != 0) {
2661 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2662 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2663 if (!first) {
2664 strlcat(value, "|", sizeof(value));
2665 }
2666 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2667 first = false;
2668 break;
2669 }
2670 }
2671 i++;
2672 }
2673 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2674 if (str)
2675 free(str);
2676 str = str_parms_to_str(reply);
2677 }
2678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 str_parms_destroy(query);
2680 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002681 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 return str;
2683}
2684
2685static uint32_t out_get_latency(const struct audio_stream_out *stream)
2686{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002687 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002689 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690
Alexy Josephaa54c872014-12-03 02:46:47 -08002691 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002692 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002693 } else if (out->realtime) {
2694 // since the buffer won't be filled up faster than realtime,
2695 // return a smaller number
2696 if (out->config.rate)
2697 period_ms = (out->af_period_multiplier * out->config.period_size *
2698 1000) / (out->config.rate);
2699 else
2700 period_ms = 0;
2701 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002702 } else {
2703 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002704 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002705 }
2706
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302707 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002708 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709}
2710
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302711static float AmpToDb(float amplification)
2712{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302713 float db = DSD_VOLUME_MIN_DB;
2714 if (amplification > 0) {
2715 db = 20 * log10(amplification);
2716 if(db < DSD_VOLUME_MIN_DB)
2717 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302718 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302719 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302720}
2721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722static int out_set_volume(struct audio_stream_out *stream, float left,
2723 float right)
2724{
Eric Laurenta9024de2013-04-04 09:19:12 -07002725 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002726 int volume[2];
2727
Eric Laurenta9024de2013-04-04 09:19:12 -07002728 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2729 /* only take left channel into account: the API is for stereo anyway */
2730 out->muted = (left == 0.0f);
2731 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002732 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302733 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002734 /*
2735 * Set mute or umute on HDMI passthrough stream.
2736 * Only take left channel into account.
2737 * Mute is 0 and unmute 1
2738 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302739 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302740 } else if (out->format == AUDIO_FORMAT_DSD){
2741 char mixer_ctl_name[128] = "DSD Volume";
2742 struct audio_device *adev = out->dev;
2743 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2744
2745 if (!ctl) {
2746 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2747 __func__, mixer_ctl_name);
2748 return -EINVAL;
2749 }
2750 volume[0] = (int)(AmpToDb(left));
2751 volume[1] = (int)(AmpToDb(right));
2752 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2753 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002754 } else {
2755 char mixer_ctl_name[128];
2756 struct audio_device *adev = out->dev;
2757 struct mixer_ctl *ctl;
2758 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002759 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002760
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002761 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2762 "Compress Playback %d Volume", pcm_device_id);
2763 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2764 if (!ctl) {
2765 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2766 __func__, mixer_ctl_name);
2767 return -EINVAL;
2768 }
2769 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2770 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2771 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2772 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002773 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002774 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 return -ENOSYS;
2777}
2778
2779static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2780 size_t bytes)
2781{
2782 struct stream_out *out = (struct stream_out *)stream;
2783 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302784 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002785 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002787 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302788
Naresh Tanniru80659832014-06-04 18:17:56 +05302789 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002790
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302791 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302792 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302793 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2794 pthread_mutex_unlock(&out->lock);
2795 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302796 } else {
2797 /* increase written size during SSR to avoid mismatch
2798 * with the written frames count in AF
2799 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002800 // bytes per frame
2801 size_t bpf = audio_bytes_per_sample(out->format) *
2802 audio_channel_count_from_out_mask(out->channel_mask);
2803 if (bpf != 0)
2804 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302805 ALOGD(" %s: sound card is not active/SSR state", __func__);
2806 ret= -EIO;
2807 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302808 }
2809 }
2810
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302811 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302812 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2813 if (audio_bytes_per_sample(out->format) != 0)
2814 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2815 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302816 goto exit;
2817 }
2818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002820 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002821 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002822 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2823 ret = voice_extn_compress_voip_start_output_stream(out);
2824 else
2825 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002826 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002827 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002829 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 goto exit;
2831 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002832
2833 if (last_known_cal_step != -1) {
2834 ALOGD("%s: retry previous failed cal level set", __func__);
2835 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838
Ashish Jain81eb2a82015-05-13 10:52:34 +05302839 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002840 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302841 adev->is_channel_status_set = true;
2842 }
2843
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002844 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002845 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002846 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002847 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002848 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2849 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302850 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2851 ALOGD("copl(%p):send next track params in gapless", out);
2852 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2853 out->send_next_track_params = false;
2854 out->is_compr_metadata_avail = false;
2855 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002856 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302857 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302858 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002859
Ashish Jain83a6cc22016-06-28 14:34:17 +05302860 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302861 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302862 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302863 pthread_mutex_unlock(&out->lock);
2864 return -EINVAL;
2865 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302866 audio_format_t dst_format = out->hal_op_format;
2867 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302868
2869 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2870 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2871
Ashish Jain83a6cc22016-06-28 14:34:17 +05302872 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302873 dst_format,
2874 buffer,
2875 src_format,
2876 frames);
2877
Ashish Jain83a6cc22016-06-28 14:34:17 +05302878 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302879 bytes_to_write);
2880
2881 /*Convert written bytes in audio flinger format*/
2882 if (ret > 0)
2883 ret = ((ret * format_to_bitwidth_table[out->format]) /
2884 format_to_bitwidth_table[dst_format]);
2885 }
2886 } else
2887 ret = compress_write(out->compr, buffer, bytes);
2888
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302889 if (ret < 0)
2890 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302891 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302892 /*msg to cb thread only if non blocking write is enabled*/
2893 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302894 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302896 } else if (-ENETRESET == ret) {
2897 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2898 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2899 pthread_mutex_unlock(&out->lock);
2900 out_standby(&out->stream.common);
2901 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 }
Ashish Jain5106d362016-05-11 19:23:33 +05302903 if ( ret == (ssize_t)bytes && !out->non_blocking)
2904 out->written += bytes;
2905
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302906 /* Call compr start only when non-zero bytes of data is there to be rendered */
2907 if (!out->playback_started && ret > 0) {
2908 int status = compress_start(out->compr);
2909 if (status < 0) {
2910 ret = status;
2911 ALOGE("%s: compr start failed with err %d", __func__, errno);
2912 goto exit;
2913 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07002914 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 out->playback_started = 1;
2916 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002917
2918 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2919 popcount(out->channel_mask),
2920 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 }
2922 pthread_mutex_unlock(&out->lock);
2923 return ret;
2924 } else {
2925 if (out->pcm) {
2926 if (out->muted)
2927 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002928
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302929 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002930
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002931 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002932
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002933 if (out->config.rate)
2934 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2935 out->config.rate;
2936
2937 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2938
2939 request_out_focus(out, ns);
2940
2941 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002942 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002943 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302944 out->convert_buffer != NULL) {
2945
2946 memcpy_by_audio_format(out->convert_buffer,
2947 out->hal_op_format,
2948 buffer,
2949 out->hal_ip_format,
2950 out->config.period_size * out->config.channels);
2951
2952 ret = pcm_write(out->pcm, out->convert_buffer,
2953 (out->config.period_size *
2954 out->config.channels *
2955 format_to_bitwidth_table[out->hal_op_format]));
2956 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002957 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302958 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002959
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002960 release_out_focus(out);
2961
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302962 if (ret < 0)
2963 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302964 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2965 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2966 else
2967 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002968 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 }
2970
2971exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302972 /* ToDo: There may be a corner case when SSR happens back to back during
2973 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302974 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302975 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302976 }
2977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 pthread_mutex_unlock(&out->lock);
2979
2980 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002981 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002982 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302983 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302984 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302985 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302986 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302987 out->standby = true;
2988 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302990 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2991 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2992 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 }
2994 return bytes;
2995}
2996
2997static int out_get_render_position(const struct audio_stream_out *stream,
2998 uint32_t *dsp_frames)
2999{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303001 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003002
3003 if (dsp_frames == NULL)
3004 return -EINVAL;
3005
3006 *dsp_frames = 0;
3007 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003008 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303009
3010 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3011 * this operation and adev_close_output_stream(where out gets reset).
3012 */
3013 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3014 *dsp_frames = get_actual_pcm_frames_rendered(out);
3015 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3016 return 0;
3017 }
3018
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003019 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303020 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303021 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303023 if (ret < 0)
3024 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003025 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303026 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027 }
3028 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303029 if (-ENETRESET == ret) {
3030 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3031 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3032 return -EINVAL;
3033 } else if(ret < 0) {
3034 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3035 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303036 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3037 /*
3038 * Handle corner case where compress session is closed during SSR
3039 * and timestamp is queried
3040 */
3041 ALOGE(" ERROR: sound card not active, return error");
3042 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303043 } else {
3044 return 0;
3045 }
Zhou Song32a556e2015-05-05 10:46:56 +08003046 } else if (audio_is_linear_pcm(out->format)) {
3047 *dsp_frames = out->written;
3048 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 } else
3050 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051}
3052
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003053static int out_add_audio_effect(const struct audio_stream *stream __unused,
3054 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055{
3056 return 0;
3057}
3058
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003059static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3060 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061{
3062 return 0;
3063}
3064
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003065static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3066 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067{
3068 return -EINVAL;
3069}
3070
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003071static int out_get_presentation_position(const struct audio_stream_out *stream,
3072 uint64_t *frames, struct timespec *timestamp)
3073{
3074 struct stream_out *out = (struct stream_out *)stream;
3075 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003076 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003077
Ashish Jain5106d362016-05-11 19:23:33 +05303078 /* below piece of code is not guarded against any lock because audioFliner serializes
3079 * this operation and adev_close_output_stream( where out gets reset).
3080 */
3081 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3082 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3083 *frames = get_actual_pcm_frames_rendered(out);
3084 /* this is the best we can do */
3085 clock_gettime(CLOCK_MONOTONIC, timestamp);
3086 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3087 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3088 return 0;
3089 }
3090
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003091 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003092
Ashish Jain5106d362016-05-11 19:23:33 +05303093 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3094 ret = compress_get_tstamp(out->compr, &dsp_frames,
3095 &out->sample_rate);
3096 ALOGVV("%s rendered frames %ld sample_rate %d",
3097 __func__, dsp_frames, out->sample_rate);
3098 *frames = dsp_frames;
3099 if (ret < 0)
3100 ret = -errno;
3101 if (-ENETRESET == ret) {
3102 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3103 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3104 ret = -EINVAL;
3105 } else
3106 ret = 0;
3107 /* this is the best we can do */
3108 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003109 } else {
3110 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003111 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003112 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3113 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003114 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003115 // This adjustment accounts for buffering after app processor.
3116 // It is based on estimated DSP latency per use case, rather than exact.
3117 signed_frames -=
3118 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3119
Eric Laurent949a0892013-09-20 09:20:13 -07003120 // It would be unusual for this value to be negative, but check just in case ...
3121 if (signed_frames >= 0) {
3122 *frames = signed_frames;
3123 ret = 0;
3124 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003125 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303126 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3127 *frames = out->written;
3128 clock_gettime(CLOCK_MONOTONIC, timestamp);
3129 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003130 }
3131 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003132 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003133 return ret;
3134}
3135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136static int out_set_callback(struct audio_stream_out *stream,
3137 stream_callback_t callback, void *cookie)
3138{
3139 struct stream_out *out = (struct stream_out *)stream;
3140
3141 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003142 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143 out->offload_callback = callback;
3144 out->offload_cookie = cookie;
3145 pthread_mutex_unlock(&out->lock);
3146 return 0;
3147}
3148
3149static int out_pause(struct audio_stream_out* stream)
3150{
3151 struct stream_out *out = (struct stream_out *)stream;
3152 int status = -ENOSYS;
3153 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003154 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003155 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003156 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003157 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303158 struct audio_device *adev = out->dev;
3159 int snd_scard_state = get_snd_card_state(adev);
3160
3161 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3162 status = compress_pause(out->compr);
3163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003164 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003165
Mingming Yin21854652016-04-13 11:54:02 -07003166 if (audio_extn_passthru_is_active()) {
3167 ALOGV("offload use case, pause passthru");
3168 audio_extn_passthru_on_pause(out);
3169 }
3170
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303171 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003172 audio_extn_dts_notify_playback_state(out->usecase, 0,
3173 out->sample_rate, popcount(out->channel_mask),
3174 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003175 }
3176 pthread_mutex_unlock(&out->lock);
3177 }
3178 return status;
3179}
3180
3181static int out_resume(struct audio_stream_out* stream)
3182{
3183 struct stream_out *out = (struct stream_out *)stream;
3184 int status = -ENOSYS;
3185 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003186 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003187 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003188 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003189 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303191 struct audio_device *adev = out->dev;
3192 int snd_scard_state = get_snd_card_state(adev);
3193
Mingming Yin21854652016-04-13 11:54:02 -07003194 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3195 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3196 pthread_mutex_lock(&out->dev->lock);
3197 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003198 pthread_mutex_unlock(&out->dev->lock);
3199 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303200 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003201 }
3202 if (!status) {
3203 out->offload_state = OFFLOAD_STATE_PLAYING;
3204 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303205 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003206 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3207 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003208 }
3209 pthread_mutex_unlock(&out->lock);
3210 }
3211 return status;
3212}
3213
3214static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3215{
3216 struct stream_out *out = (struct stream_out *)stream;
3217 int status = -ENOSYS;
3218 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003219 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003220 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003221 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3222 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3223 else
3224 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3225 pthread_mutex_unlock(&out->lock);
3226 }
3227 return status;
3228}
3229
3230static int out_flush(struct audio_stream_out* stream)
3231{
3232 struct stream_out *out = (struct stream_out *)stream;
3233 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003234 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003235 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003236 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003237 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3238 stop_compressed_output_l(out);
3239 out->written = 0;
3240 } else {
3241 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3242 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003243 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003244 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003245 return 0;
3246 }
3247 return -ENOSYS;
3248}
3249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250/** audio_stream_in implementation **/
3251static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3252{
3253 struct stream_in *in = (struct stream_in *)stream;
3254
3255 return in->config.rate;
3256}
3257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003258static int in_set_sample_rate(struct audio_stream *stream __unused,
3259 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260{
3261 return -ENOSYS;
3262}
3263
3264static size_t in_get_buffer_size(const struct audio_stream *stream)
3265{
3266 struct stream_in *in = (struct stream_in *)stream;
3267
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003268 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3269 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003270 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3271 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003272
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003273 return in->config.period_size * in->af_period_multiplier *
3274 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
3277static uint32_t in_get_channels(const struct audio_stream *stream)
3278{
3279 struct stream_in *in = (struct stream_in *)stream;
3280
3281 return in->channel_mask;
3282}
3283
3284static audio_format_t in_get_format(const struct audio_stream *stream)
3285{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003286 struct stream_in *in = (struct stream_in *)stream;
3287
3288 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289}
3290
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003291static int in_set_format(struct audio_stream *stream __unused,
3292 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293{
3294 return -ENOSYS;
3295}
3296
3297static int in_standby(struct audio_stream *stream)
3298{
3299 struct stream_in *in = (struct stream_in *)stream;
3300 struct audio_device *adev = in->dev;
3301 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303302 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3303 stream, in->usecase, use_case_table[in->usecase]);
3304
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003305 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003306 if (!in->standby && in->is_st_session) {
3307 ALOGD("%s: sound trigger pcm stop lab", __func__);
3308 audio_extn_sound_trigger_stop_lab(in);
3309 in->standby = 1;
3310 }
3311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003313 if (adev->adm_deregister_stream)
3314 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3315
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003316 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003318 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3319 voice_extn_compress_voip_close_input_stream(stream);
3320 ALOGD("VOIP input entered standby");
3321 } else {
3322 if (in->pcm) {
3323 pcm_close(in->pcm);
3324 in->pcm = NULL;
3325 }
3326 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003327 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003328 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 }
3330 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003331 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 return status;
3333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static int in_dump(const struct audio_stream *stream __unused,
3336 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return 0;
3339}
3340
3341static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3342{
3343 struct stream_in *in = (struct stream_in *)stream;
3344 struct audio_device *adev = in->dev;
3345 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003347 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303349 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 parms = str_parms_create_str(kvpairs);
3351
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303352 if (!parms)
3353 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003354 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003355 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003356
3357 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3358 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 val = atoi(value);
3360 /* no audio source uses val == 0 */
3361 if ((in->source != val) && (val != 0)) {
3362 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003363 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3364 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3365 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003366 (in->config.rate == 8000 || in->config.rate == 16000 ||
3367 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003368 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003369 err = voice_extn_compress_voip_open_input_stream(in);
3370 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003371 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003372 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003373 }
3374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 }
3376 }
3377
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003378 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3379 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003381 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 in->device = val;
3383 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003384 if (!in->standby && !in->is_st_session) {
3385 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003386 if (adev->adm_on_routing_change)
3387 adev->adm_on_routing_change(adev->adm_data,
3388 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003389 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003390 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 }
3392 }
3393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003395 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396
3397 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303398error:
Eric Laurent994a6932013-07-17 11:51:42 -07003399 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 return ret;
3401}
3402
3403static char* in_get_parameters(const struct audio_stream *stream,
3404 const char *keys)
3405{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003406 struct stream_in *in = (struct stream_in *)stream;
3407 struct str_parms *query = str_parms_create_str(keys);
3408 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003409 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003410
3411 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003412 if (reply) {
3413 str_parms_destroy(reply);
3414 }
3415 if (query) {
3416 str_parms_destroy(query);
3417 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003418 ALOGE("in_get_parameters: failed to create query or reply");
3419 return NULL;
3420 }
3421
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003422 ALOGV("%s: enter: keys - %s", __func__, keys);
3423
3424 voice_extn_in_get_parameters(in, query, reply);
3425
3426 str = str_parms_to_str(reply);
3427 str_parms_destroy(query);
3428 str_parms_destroy(reply);
3429
3430 ALOGV("%s: exit: returns - %s", __func__, str);
3431 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432}
3433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003434static int in_set_gain(struct audio_stream_in *stream __unused,
3435 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436{
3437 return 0;
3438}
3439
3440static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3441 size_t bytes)
3442{
3443 struct stream_in *in = (struct stream_in *)stream;
3444 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303445 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303446 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303447 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003449 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303450
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003451 if (in->is_st_session) {
3452 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3453 /* Read from sound trigger HAL */
3454 audio_extn_sound_trigger_read(in, buffer, bytes);
3455 pthread_mutex_unlock(&in->lock);
3456 return bytes;
3457 }
3458
Ashish Jainbbce4322016-02-16 13:25:27 +05303459 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003460 ALOGD(" %s: sound card is not active/SSR state", __func__);
3461 ret= -EIO;;
3462 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303463 }
3464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003466 pthread_mutex_lock(&adev->lock);
3467 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3468 ret = voice_extn_compress_voip_start_input_stream(in);
3469 else
3470 ret = start_input_stream(in);
3471 pthread_mutex_unlock(&adev->lock);
3472 if (ret != 0) {
3473 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474 }
3475 in->standby = 0;
3476 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003478 // what's the duration requested by the client?
3479 long ns = 0;
3480
3481 if (in->config.rate)
3482 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3483 in->config.rate;
3484
3485 request_in_focus(in, ns);
3486 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303489 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003490 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303491 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003492 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003493 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003494 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303495 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003496 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303497 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3498 if (bytes % 4 == 0) {
3499 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3500 int_buf_stream = buffer;
3501 for (size_t itt=0; itt < bytes/4 ; itt++) {
3502 int_buf_stream[itt] >>= 8;
3503 }
3504 } else {
3505 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3506 ret = -EINVAL;
3507 goto exit;
3508 }
3509 } if (ret < 0) {
3510 ret = -errno;
3511 }
3512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 }
3514
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003515 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 /*
3518 * Instead of writing zeroes here, we could trust the hardware
3519 * to always provide zeroes when muted.
3520 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303521 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3522 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 memset(buffer, 0, bytes);
3524
3525exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303526 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303527 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003528 if (-ENETRESET == ret)
3529 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 pthread_mutex_unlock(&in->lock);
3532
3533 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303534 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303535 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303536 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303537 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303538 in->standby = true;
3539 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303540 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003542 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303543 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303544 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 }
3546 return bytes;
3547}
3548
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003549static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550{
3551 return 0;
3552}
3553
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003554static int add_remove_audio_effect(const struct audio_stream *stream,
3555 effect_handle_t effect,
3556 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003558 struct stream_in *in = (struct stream_in *)stream;
3559 int status = 0;
3560 effect_descriptor_t desc;
3561
3562 status = (*effect)->get_descriptor(effect, &desc);
3563 if (status != 0)
3564 return status;
3565
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003566 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003567 pthread_mutex_lock(&in->dev->lock);
3568 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3569 in->enable_aec != enable &&
3570 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3571 in->enable_aec = enable;
3572 if (!in->standby)
3573 select_devices(in->dev, in->usecase);
3574 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003575 if (in->enable_ns != enable &&
3576 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3577 in->enable_ns = enable;
3578 if (!in->standby)
3579 select_devices(in->dev, in->usecase);
3580 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003581 pthread_mutex_unlock(&in->dev->lock);
3582 pthread_mutex_unlock(&in->lock);
3583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584 return 0;
3585}
3586
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003587static int in_add_audio_effect(const struct audio_stream *stream,
3588 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589{
Eric Laurent994a6932013-07-17 11:51:42 -07003590 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003591 return add_remove_audio_effect(stream, effect, true);
3592}
3593
3594static int in_remove_audio_effect(const struct audio_stream *stream,
3595 effect_handle_t effect)
3596{
Eric Laurent994a6932013-07-17 11:51:42 -07003597 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003598 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599}
3600
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303601int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 audio_io_handle_t handle,
3603 audio_devices_t devices,
3604 audio_output_flags_t flags,
3605 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003606 struct audio_stream_out **stream_out,
3607 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608{
3609 struct audio_device *adev = (struct audio_device *)dev;
3610 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303611 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003612 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303615
3616 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3617 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003618 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303619 return -EINVAL;
3620 }
3621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3623
Mingming Yin3a941d42016-02-17 18:08:05 -08003624 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3625 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303626 devices, flags, &out->stream);
3627
3628
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003629 if (!out) {
3630 return -ENOMEM;
3631 }
3632
Haynes Mathew George204045b2015-02-25 20:32:03 -08003633 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003634 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003635 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 if (devices == AUDIO_DEVICE_NONE)
3638 devices = AUDIO_DEVICE_OUT_SPEAKER;
3639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 out->flags = flags;
3641 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003642 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003643 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003644 out->sample_rate = config->sample_rate;
3645 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3646 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003647 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003648 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003649 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303650 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651
Mingming Yin3a941d42016-02-17 18:08:05 -08003652 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3653 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3654 pthread_mutex_lock(&adev->lock);
3655 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3656 ret = read_hdmi_sink_caps(out);
3657 pthread_mutex_unlock(&adev->lock);
3658 if (ret != 0) {
3659 if (ret == -ENOSYS) {
3660 /* ignore and go with default */
3661 ret = 0;
3662 } else {
3663 ALOGE("error reading hdmi sink caps");
3664 goto error_open;
3665 }
3666 }
3667 }
3668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003670 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303671 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3672 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003673 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3674 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3675
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003676 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003677 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3678 /*
3679 * Do not handle stereo output in Multi-channel cases
3680 * Stereo case is handled in normal playback path
3681 */
3682 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3683 ret = AUDIO_CHANNEL_OUT_STEREO;
3684 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003685
3686 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3687 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003688 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003689 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003690 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003691
3692 if (config->sample_rate == 0)
3693 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3694 if (config->channel_mask == 0)
3695 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003696 if (config->format == 0)
3697 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003698
3699 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003700 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003701 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3703 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003705 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003707 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3708 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003709 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003710 ret = voice_extn_compress_voip_open_output_stream(out);
3711 if (ret != 0) {
3712 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3713 __func__, ret);
3714 goto error_open;
3715 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003716 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3717 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3718
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3720 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3721 ALOGE("%s: Unsupported Offload information", __func__);
3722 ret = -EINVAL;
3723 goto error_open;
3724 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003725
Mingming Yin3a941d42016-02-17 18:08:05 -08003726 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003727 if(config->offload_info.format == 0)
3728 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003729 if (config->offload_info.sample_rate == 0)
3730 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003731 }
3732
Mingming Yin90310102013-11-13 16:57:00 -08003733 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303734 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003735 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003736 ret = -EINVAL;
3737 goto error_open;
3738 }
3739
3740 out->compr_config.codec = (struct snd_codec *)
3741 calloc(1, sizeof(struct snd_codec));
3742
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003743 if (!out->compr_config.codec) {
3744 ret = -ENOMEM;
3745 goto error_open;
3746 }
3747
vivek mehta0ea887a2015-08-26 14:01:20 -07003748 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303749 out->stream.pause = out_pause;
3750 out->stream.flush = out_flush;
3751 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003752 out->usecase = get_offload_usecase(adev, true);
3753 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003754 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003755 out->stream.set_callback = out_set_callback;
3756 out->stream.pause = out_pause;
3757 out->stream.resume = out_resume;
3758 out->stream.drain = out_drain;
3759 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003760 out->usecase = get_offload_usecase(adev, false);
3761 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003762 }
vivek mehta446c3962015-09-14 10:57:35 -07003763
3764 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003765 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3766 config->format == 0 && config->sample_rate == 0 &&
3767 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003768 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003769 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3770 } else {
3771 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3772 ret = -EEXIST;
3773 goto error_open;
3774 }
vivek mehta446c3962015-09-14 10:57:35 -07003775 }
3776
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003777 if (config->offload_info.channel_mask)
3778 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003779 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003780 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003781 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003782 } else {
3783 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3784 ret = -EINVAL;
3785 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003786 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003787
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003788 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789 out->sample_rate = config->offload_info.sample_rate;
3790
Mingming Yin3ee55c62014-08-04 14:23:35 -07003791 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303793 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3794 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3795 audio_extn_dolby_send_ddp_endp_params(adev);
3796 audio_extn_dolby_set_dmid(adev);
3797 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003798
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003799 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003800 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003801 out->compr_config.codec->bit_rate =
3802 config->offload_info.bit_rate;
3803 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303804 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303806 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003807 /*TODO: Do we need to change it for passthrough */
3808 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809
Manish Dewangana6fc5442015-08-24 20:30:31 +05303810 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3811 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3812 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3813 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303814
3815 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3816 AUDIO_FORMAT_PCM) {
3817
3818 /*Based on platform support, configure appropriate alsa format for corresponding
3819 *hal input format.
3820 */
3821 out->compr_config.codec->format = hal_format_to_alsa(
3822 config->offload_info.format);
3823
Ashish Jain83a6cc22016-06-28 14:34:17 +05303824 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303825 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303826 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303827
3828 /*for direct PCM playback populate bit_width based on selected alsa format as
3829 *hal input format and alsa format might differ based on platform support.
3830 */
3831 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303832 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303833
3834 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3835
3836 /* Check if alsa session is configured with the same format as HAL input format,
3837 * if not then derive correct fragment size needed to accomodate the
3838 * conversion of HAL input format to alsa format.
3839 */
3840 audio_extn_utils_update_direct_pcm_fragment_size(out);
3841
3842 /*if hal input and output fragment size is different this indicates HAL input format is
3843 *not same as the alsa format
3844 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303845 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303846 /*Allocate a buffer to convert input data to the alsa configured format.
3847 *size of convert buffer is equal to the size required to hold one fragment size
3848 *worth of pcm data, this is because flinger does not write more than fragment_size
3849 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303850 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3851 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303852 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3853 ret = -ENOMEM;
3854 goto error_open;
3855 }
3856 }
3857 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3858 out->compr_config.fragment_size =
3859 audio_extn_passthru_get_buffer_size(&config->offload_info);
3860 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3861 } else {
3862 out->compr_config.fragment_size =
3863 platform_get_compress_offload_buffer_size(&config->offload_info);
3864 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3865 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003866
Amit Shekhar6f461b12014-08-01 14:52:58 -07003867 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303868 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003870 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3871 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003872
Alexy Josephaa54c872014-12-03 02:46:47 -08003873
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003874 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303875 out->send_next_track_params = false;
3876 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003877 out->offload_state = OFFLOAD_STATE_IDLE;
3878 out->playback_started = 0;
3879
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003880 audio_extn_dts_create_state_notifier_node(out->usecase);
3881
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003882 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3883 __func__, config->offload_info.version,
3884 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303885
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303886 /* Check if DSD audio format is supported in codec
3887 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303888 */
3889
3890 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303891 (!platform_check_codec_dsd_support(adev->platform) ||
3892 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303893 ret = -EINVAL;
3894 goto error_open;
3895 }
3896
Ashish Jain5106d362016-05-11 19:23:33 +05303897 /* Disable gapless if any of the following is true
3898 * passthrough playback
3899 * AV playback
3900 * Direct PCM playback
3901 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303902 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303903 (config->format == AUDIO_FORMAT_DSD) ||
3904 config->offload_info.has_video ||
3905 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303906 check_and_set_gapless_mode(adev, false);
3907 } else
3908 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003909
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303910 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003911 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3912 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303913 if (config->format == AUDIO_FORMAT_DSD) {
3914 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3915 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
3916 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07003917
3918 create_offload_callback_thread(out);
3919
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003920 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303921 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003922 if (ret != 0) {
3923 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3924 __func__, ret);
3925 goto error_open;
3926 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003927 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3928 if (config->sample_rate == 0)
3929 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3930 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3931 config->sample_rate != 8000) {
3932 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3933 ret = -EINVAL;
3934 goto error_open;
3935 }
3936 out->sample_rate = config->sample_rate;
3937 out->config.rate = config->sample_rate;
3938 if (config->format == AUDIO_FORMAT_DEFAULT)
3939 config->format = AUDIO_FORMAT_PCM_16_BIT;
3940 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3941 config->format = AUDIO_FORMAT_PCM_16_BIT;
3942 ret = -EINVAL;
3943 goto error_open;
3944 }
3945 out->format = config->format;
3946 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3947 out->config = pcm_config_afe_proxy_playback;
3948 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003949 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05303950 unsigned int channels = 0;
3951 /*Update config params to default if not set by the caller*/
3952 if (config->sample_rate == 0)
3953 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3954 if (config->channel_mask == AUDIO_CHANNEL_NONE)
3955 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3956 if (config->format == AUDIO_FORMAT_DEFAULT)
3957 config->format = AUDIO_FORMAT_PCM_16_BIT;
3958
3959 channels = audio_channel_count_from_out_mask(out->channel_mask);
3960
Ashish Jain83a6cc22016-06-28 14:34:17 +05303961 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3962 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003963 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3964 out->flags);
3965 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303966 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3967 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3968 out->config = pcm_config_low_latency;
3969 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3970 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3971 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05303972 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
3973 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
3974 if (out->config.period_size <= 0) {
3975 ALOGE("Invalid configuration period size is not valid");
3976 ret = -EINVAL;
3977 goto error_open;
3978 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05303979 } else {
3980 /* primary path is the default path selected if no other outputs are available/suitable */
3981 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3982 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3983 }
3984 out->hal_ip_format = format = out->format;
3985 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3986 out->hal_op_format = pcm_format_to_hal(out->config.format);
3987 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3988 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003989 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05303990 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303991 if (out->hal_ip_format != out->hal_op_format) {
3992 uint32_t buffer_size = out->config.period_size *
3993 format_to_bitwidth_table[out->hal_op_format] *
3994 out->config.channels;
3995 out->convert_buffer = calloc(1, buffer_size);
3996 if (out->convert_buffer == NULL){
3997 ALOGE("Allocation failed for convert buffer for size %d",
3998 out->compr_config.fragment_size);
3999 ret = -ENOMEM;
4000 goto error_open;
4001 }
4002 ALOGD("Convert buffer allocated of size %d", buffer_size);
4003 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 }
4005
Ashish Jain83a6cc22016-06-28 14:34:17 +05304006 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4007 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4008
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004009 /* TODO remove this hardcoding and check why width is zero*/
4010 if (out->bit_width == 0)
4011 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004012 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
4013 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004014 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05304015 out->bit_width, out->channel_mask,
4016 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004017 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4018 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4019 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004020 if(adev->primary_output == NULL)
4021 adev->primary_output = out;
4022 else {
4023 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004024 ret = -EEXIST;
4025 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004026 }
4027 }
4028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029 /* Check if this usecase is already existing */
4030 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004031 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4032 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004033 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004035 ret = -EEXIST;
4036 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 }
4038 pthread_mutex_unlock(&adev->lock);
4039
4040 out->stream.common.get_sample_rate = out_get_sample_rate;
4041 out->stream.common.set_sample_rate = out_set_sample_rate;
4042 out->stream.common.get_buffer_size = out_get_buffer_size;
4043 out->stream.common.get_channels = out_get_channels;
4044 out->stream.common.get_format = out_get_format;
4045 out->stream.common.set_format = out_set_format;
4046 out->stream.common.standby = out_standby;
4047 out->stream.common.dump = out_dump;
4048 out->stream.common.set_parameters = out_set_parameters;
4049 out->stream.common.get_parameters = out_get_parameters;
4050 out->stream.common.add_audio_effect = out_add_audio_effect;
4051 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4052 out->stream.get_latency = out_get_latency;
4053 out->stream.set_volume = out_set_volume;
4054 out->stream.write = out_write;
4055 out->stream.get_render_position = out_get_render_position;
4056 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004057 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004059 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004061 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004062 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063
4064 config->format = out->stream.common.get_format(&out->stream.common);
4065 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4066 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4067
4068 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304069 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004070 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004071
4072 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4073 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4074 popcount(out->channel_mask), out->playback_started);
4075
Eric Laurent994a6932013-07-17 11:51:42 -07004076 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004078
4079error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304080 if (out->convert_buffer)
4081 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004082 free(out);
4083 *stream_out = NULL;
4084 ALOGD("%s: exit: ret %d", __func__, ret);
4085 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086}
4087
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304088void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 struct audio_stream_out *stream)
4090{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004091 struct stream_out *out = (struct stream_out *)stream;
4092 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004093 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004094
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304095 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4096
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004097 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304098 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004099 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304100 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004101 if(ret != 0)
4102 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4103 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004104 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004105 out_standby(&stream->common);
4106
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004107 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004108 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004109 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004110 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004111 if (out->compr_config.codec != NULL)
4112 free(out->compr_config.codec);
4113 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004114
Ashish Jain83a6cc22016-06-28 14:34:17 +05304115 if (out->convert_buffer != NULL) {
4116 free(out->convert_buffer);
4117 out->convert_buffer = NULL;
4118 }
4119
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004120 if (adev->voice_tx_output == out)
4121 adev->voice_tx_output = NULL;
4122
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004123 pthread_cond_destroy(&out->cond);
4124 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004126 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127}
4128
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004129static void close_compress_sessions(struct audio_device *adev)
4130{
Mingming Yin7b762e72015-03-04 13:47:32 -08004131 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304132 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004133 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004134 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304135
4136 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004137 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304138 if (is_offload_usecase(usecase->id)) {
4139 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004140 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4141 out = usecase->stream.out;
4142 pthread_mutex_unlock(&adev->lock);
4143 out_standby(&out->stream.common);
4144 pthread_mutex_lock(&adev->lock);
4145 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304146 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004147 }
4148 pthread_mutex_unlock(&adev->lock);
4149}
4150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4152{
4153 struct audio_device *adev = (struct audio_device *)dev;
4154 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004156 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004157 int ret;
4158 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004160 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304163 if (!parms)
4164 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004165 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4166 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304167 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304168 if (strstr(snd_card_status, "OFFLINE")) {
4169 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304170 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004171 //close compress sessions on OFFLINE status
4172 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304173 } else if (strstr(snd_card_status, "ONLINE")) {
4174 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304175 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004176 //send dts hpx license if enabled
4177 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304178 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304179 }
4180
4181 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004182 status = voice_set_parameters(adev, parms);
4183 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004184 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004186 status = platform_set_parameters(adev->platform, parms);
4187 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004188 goto done;
4189
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004190 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4191 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004192 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4194 adev->bluetooth_nrec = true;
4195 else
4196 adev->bluetooth_nrec = false;
4197 }
4198
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004199 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4200 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4202 adev->screen_off = false;
4203 else
4204 adev->screen_off = true;
4205 }
4206
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004207 ret = str_parms_get_int(parms, "rotation", &val);
4208 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004209 bool reverse_speakers = false;
4210 switch(val) {
4211 // FIXME: note that the code below assumes that the speakers are in the correct placement
4212 // relative to the user when the device is rotated 90deg from its default rotation. This
4213 // assumption is device-specific, not platform-specific like this code.
4214 case 270:
4215 reverse_speakers = true;
4216 break;
4217 case 0:
4218 case 90:
4219 case 180:
4220 break;
4221 default:
4222 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004223 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004224 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004225 if (status == 0) {
4226 if (adev->speaker_lr_swap != reverse_speakers) {
4227 adev->speaker_lr_swap = reverse_speakers;
4228 // only update the selected device if there is active pcm playback
4229 struct audio_usecase *usecase;
4230 struct listnode *node;
4231 list_for_each(node, &adev->usecase_list) {
4232 usecase = node_to_item(node, struct audio_usecase, list);
4233 if (usecase->type == PCM_PLAYBACK) {
4234 select_devices(adev, usecase->id);
4235 break;
4236 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004237 }
4238 }
4239 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004240 }
4241
Mingming Yin514a8bc2014-07-29 15:22:21 -07004242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4243 if (ret >= 0) {
4244 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4245 adev->bt_wb_speech_enabled = true;
4246 else
4247 adev->bt_wb_speech_enabled = false;
4248 }
4249
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004250 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4251 if (ret >= 0) {
4252 val = atoi(value);
4253 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004254 ALOGV("cache new ext disp type and edid");
4255 ret = platform_get_ext_disp_type(adev->platform);
4256 if (ret < 0) {
4257 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004258 status = ret;
4259 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004260 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004261 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004262 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004263 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004264 /*
4265 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4266 * Per AudioPolicyManager, USB device is higher priority than WFD.
4267 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4268 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4269 * starting voice call on USB
4270 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004271 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4272 if (ret >= 0) {
4273 audio_extn_usb_add_device(val, atoi(value));
4274 }
vivek mehta344576a2016-04-12 18:56:03 -07004275 ALOGV("detected USB connect .. disable proxy");
4276 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004277 }
4278 }
4279
4280 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4281 if (ret >= 0) {
4282 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004283 /*
4284 * The HDMI / Displayport disconnect handling has been moved to
4285 * audio extension to ensure that its parameters are not
4286 * invalidated prior to updating sysfs of the disconnect event
4287 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4288 */
4289 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004290 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004291 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4292 if (ret >= 0) {
4293 audio_extn_usb_remove_device(val, atoi(value));
4294 }
vivek mehta344576a2016-04-12 18:56:03 -07004295 ALOGV("detected USB disconnect .. enable proxy");
4296 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004297 }
4298 }
4299
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304300 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4301 if (ret >= 0) {
4302 struct audio_usecase *usecase;
4303 struct listnode *node;
4304 list_for_each(node, &adev->usecase_list) {
4305 usecase = node_to_item(node, struct audio_usecase, list);
4306 if ((usecase->type == PCM_PLAYBACK) &&
4307 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4308 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304309 lock_output_stream(usecase->stream.out);
4310 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304311 //force device switch to re configure encoder
4312 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304313 audio_extn_a2dp_set_handoff_mode(false);
4314 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304315 break;
4316 }
4317 }
4318 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304319 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004320done:
4321 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004322 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304323error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004324 ALOGV("%s: exit with code(%d)", __func__, status);
4325 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326}
4327
4328static char* adev_get_parameters(const struct audio_hw_device *dev,
4329 const char *keys)
4330{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004331 struct audio_device *adev = (struct audio_device *)dev;
4332 struct str_parms *reply = str_parms_create();
4333 struct str_parms *query = str_parms_create_str(keys);
4334 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304335 char value[256] = {0};
4336 int ret = 0;
4337
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004338 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004339 if (reply) {
4340 str_parms_destroy(reply);
4341 }
4342 if (query) {
4343 str_parms_destroy(query);
4344 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004345 ALOGE("adev_get_parameters: failed to create query or reply");
4346 return NULL;
4347 }
4348
Naresh Tannirud7205b62014-06-20 02:54:48 +05304349 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4350 sizeof(value));
4351 if (ret >=0) {
4352 int val = 1;
4353 pthread_mutex_lock(&adev->snd_card_status.lock);
4354 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4355 val = 0;
4356 pthread_mutex_unlock(&adev->snd_card_status.lock);
4357 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4358 goto exit;
4359 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004360
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004361 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004362 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004363 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004364 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304365 pthread_mutex_unlock(&adev->lock);
4366
Naresh Tannirud7205b62014-06-20 02:54:48 +05304367exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004368 str = str_parms_to_str(reply);
4369 str_parms_destroy(query);
4370 str_parms_destroy(reply);
4371
4372 ALOGV("%s: exit: returns - %s", __func__, str);
4373 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374}
4375
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004376static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377{
4378 return 0;
4379}
4380
4381static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4382{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004383 int ret;
4384 struct audio_device *adev = (struct audio_device *)dev;
4385 pthread_mutex_lock(&adev->lock);
4386 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004387 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004388 pthread_mutex_unlock(&adev->lock);
4389 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390}
4391
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004392static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4393 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394{
4395 return -ENOSYS;
4396}
4397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004398static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4399 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400{
4401 return -ENOSYS;
4402}
4403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004404static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4405 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406{
4407 return -ENOSYS;
4408}
4409
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004410static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4411 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412{
4413 return -ENOSYS;
4414}
4415
4416static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4417{
4418 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 pthread_mutex_lock(&adev->lock);
4421 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004422 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004424 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004425 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004426 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004427 adev->current_call_output = NULL;
4428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429 }
4430 pthread_mutex_unlock(&adev->lock);
4431 return 0;
4432}
4433
4434static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4435{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004436 int ret;
4437
4438 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004439 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004440 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4441 pthread_mutex_unlock(&adev->lock);
4442
4443 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444}
4445
4446static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4447{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004448 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004449 return 0;
4450}
4451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004452static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453 const struct audio_config *config)
4454{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004455 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004457 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4458 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459}
4460
4461static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004462 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463 audio_devices_t devices,
4464 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004465 struct audio_stream_in **stream_in,
4466 audio_input_flags_t flags __unused,
4467 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004468 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469{
4470 struct audio_device *adev = (struct audio_device *)dev;
4471 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004472 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004473 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004474 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304475 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304478 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4479 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482
4483 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004484
4485 if (!in) {
4486 ALOGE("failed to allocate input stream");
4487 return -ENOMEM;
4488 }
4489
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304490 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304491 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4492 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004493 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004494 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496 in->stream.common.get_sample_rate = in_get_sample_rate;
4497 in->stream.common.set_sample_rate = in_set_sample_rate;
4498 in->stream.common.get_buffer_size = in_get_buffer_size;
4499 in->stream.common.get_channels = in_get_channels;
4500 in->stream.common.get_format = in_get_format;
4501 in->stream.common.set_format = in_set_format;
4502 in->stream.common.standby = in_standby;
4503 in->stream.common.dump = in_dump;
4504 in->stream.common.set_parameters = in_set_parameters;
4505 in->stream.common.get_parameters = in_get_parameters;
4506 in->stream.common.add_audio_effect = in_add_audio_effect;
4507 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4508 in->stream.set_gain = in_set_gain;
4509 in->stream.read = in_read;
4510 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4511
4512 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004513 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004515 in->standby = 1;
4516 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004517 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004518 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519
4520 /* Update config params with the requested sample rate and channels */
4521 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004522 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4523 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4524 is_low_latency = true;
4525#if LOW_LATENCY_CAPTURE_USE_CASE
4526 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4527#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004528 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004529 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004530
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004531 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004532 if (in->realtime) {
4533 in->config = pcm_config_audio_capture_rt;
4534 in->sample_rate = in->config.rate;
4535 in->af_period_multiplier = af_period_multiplier;
4536 } else {
4537 in->config = pcm_config_audio_capture;
4538 in->config.rate = config->sample_rate;
4539 in->sample_rate = config->sample_rate;
4540 in->af_period_multiplier = 1;
4541 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304542 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004544 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304545 if (adev->mode != AUDIO_MODE_IN_CALL) {
4546 ret = -EINVAL;
4547 goto err_open;
4548 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004549 if (config->sample_rate == 0)
4550 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4551 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4552 config->sample_rate != 8000) {
4553 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4554 ret = -EINVAL;
4555 goto err_open;
4556 }
4557 if (config->format == AUDIO_FORMAT_DEFAULT)
4558 config->format = AUDIO_FORMAT_PCM_16_BIT;
4559 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4560 config->format = AUDIO_FORMAT_PCM_16_BIT;
4561 ret = -EINVAL;
4562 goto err_open;
4563 }
4564
4565 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4566 in->config = pcm_config_afe_proxy_record;
4567 in->config.channels = channel_count;
4568 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304569 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304570 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4571 in, config, &channel_mask_updated)) {
4572 if (channel_mask_updated == true) {
4573 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4574 __func__, config->channel_mask);
4575 ret = -EINVAL;
4576 goto err_open;
4577 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304578 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004579 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004580 audio_extn_compr_cap_format_supported(config->format) &&
4581 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004582 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004583 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304584 /* restrict 24 bit capture for unprocessed source only
4585 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4586 */
4587 if (config->format == AUDIO_FORMAT_DEFAULT) {
4588 config->format = AUDIO_FORMAT_PCM_16_BIT;
4589 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4590 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4591 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4592 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4593 bool ret_error = false;
4594 in->bit_width = 24;
4595 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4596 from HAL is 24_packed and 8_24
4597 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4598 24_packed return error indicating supported format is 24_packed
4599 *> In case of any other source requesting 24 bit or float return error
4600 indicating format supported is 16 bit only.
4601
4602 on error flinger will retry with supported format passed
4603 */
4604 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4605 (source != AUDIO_SOURCE_CAMCORDER)) {
4606 config->format = AUDIO_FORMAT_PCM_16_BIT;
4607 if( config->sample_rate > 48000)
4608 config->sample_rate = 48000;
4609 ret_error = true;
4610 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4611 in->config.format = PCM_FORMAT_S24_3LE;
4612 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4613 in->config.format = PCM_FORMAT_S24_LE;
4614 } else {
4615 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4616 ret_error = true;
4617 }
4618
4619 if (ret_error) {
4620 ret = -EINVAL;
4621 goto err_open;
4622 }
4623 }
4624
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004625 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004626 if (!in->realtime) {
4627 in->format = config->format;
4628 frame_size = audio_stream_in_frame_size(&in->stream);
4629 buffer_size = get_input_buffer_size(config->sample_rate,
4630 config->format,
4631 channel_count,
4632 is_low_latency);
4633 in->config.period_size = buffer_size / frame_size;
4634 }
4635
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004636 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4637 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4638 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004639 (in->config.rate == 8000 || in->config.rate == 16000 ||
4640 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004641 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4642 voice_extn_compress_voip_open_input_stream(in);
4643 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004646 /* This stream could be for sound trigger lab,
4647 get sound trigger pcm if present */
4648 audio_extn_sound_trigger_check_and_get_session(in);
4649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004651 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004652 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653
4654err_open:
4655 free(in);
4656 *stream_in = NULL;
4657 return ret;
4658}
4659
4660static void adev_close_input_stream(struct audio_hw_device *dev,
4661 struct audio_stream_in *stream)
4662{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004663 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004664 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004665 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304666
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304667 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004668
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304669 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004670 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304671
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004672 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304673 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004674 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304675 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004676 if (ret != 0)
4677 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4678 __func__, ret);
4679 } else
4680 in_standby(&stream->common);
4681
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004682 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004683 audio_extn_ssr_deinit();
4684 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685
Mingming Yine62d7842013-10-25 16:26:03 -07004686 if(audio_extn_compr_cap_enabled() &&
4687 audio_extn_compr_cap_format_supported(in->config.format))
4688 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004689
Mingming Yinfd7607b2016-01-22 12:48:44 -08004690 if (in->is_st_session) {
4691 ALOGV("%s: sound trigger pcm stop lab", __func__);
4692 audio_extn_sound_trigger_stop_lab(in);
4693 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004694 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695 return;
4696}
4697
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004698static int adev_dump(const audio_hw_device_t *device __unused,
4699 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700{
4701 return 0;
4702}
4703
4704static int adev_close(hw_device_t *device)
4705{
4706 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004707
4708 if (!adev)
4709 return 0;
4710
4711 pthread_mutex_lock(&adev_init_lock);
4712
4713 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004714 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004715 audio_extn_listen_deinit(adev);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304716 if (audio_extn_qaf_is_enabled())
4717 audio_extn_qaf_deinit();
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004718 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004719 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004720 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004721 free(adev->snd_dev_ref_cnt);
4722 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004723 if (adev->adm_deinit)
4724 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004725 free(device);
4726 adev = NULL;
4727 }
4728 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730 return 0;
4731}
4732
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004733/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4734 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4735 * just that it _might_ work.
4736 */
4737static int period_size_is_plausible_for_low_latency(int period_size)
4738{
4739 switch (period_size) {
4740 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004741 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004742 case 240:
4743 case 320:
4744 case 480:
4745 return 1;
4746 default:
4747 return 0;
4748 }
4749}
4750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004751static int adev_open(const hw_module_t *module, const char *name,
4752 hw_device_t **device)
4753{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304754 int ret;
4755
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004756 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4758
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004759 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004760 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004761 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004762 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004763 ALOGD("%s: returning existing instance of adev", __func__);
4764 ALOGD("%s: exit", __func__);
4765 pthread_mutex_unlock(&adev_init_lock);
4766 return 0;
4767 }
4768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 adev = calloc(1, sizeof(struct audio_device));
4770
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004771 if (!adev) {
4772 pthread_mutex_unlock(&adev_init_lock);
4773 return -ENOMEM;
4774 }
4775
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004776 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4779 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4780 adev->device.common.module = (struct hw_module_t *)module;
4781 adev->device.common.close = adev_close;
4782
4783 adev->device.init_check = adev_init_check;
4784 adev->device.set_voice_volume = adev_set_voice_volume;
4785 adev->device.set_master_volume = adev_set_master_volume;
4786 adev->device.get_master_volume = adev_get_master_volume;
4787 adev->device.set_master_mute = adev_set_master_mute;
4788 adev->device.get_master_mute = adev_get_master_mute;
4789 adev->device.set_mode = adev_set_mode;
4790 adev->device.set_mic_mute = adev_set_mic_mute;
4791 adev->device.get_mic_mute = adev_get_mic_mute;
4792 adev->device.set_parameters = adev_set_parameters;
4793 adev->device.get_parameters = adev_get_parameters;
4794 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4795 adev->device.open_output_stream = adev_open_output_stream;
4796 adev->device.close_output_stream = adev_close_output_stream;
4797 adev->device.open_input_stream = adev_open_input_stream;
4798 adev->device.close_input_stream = adev_close_input_stream;
4799 adev->device.dump = adev_dump;
4800
4801 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004803 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004804 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004806 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004807 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004808 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004809 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004810 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004811 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004812 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004813 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004814 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304815 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304816 adev->perf_lock_opts[0] = 0x101;
4817 adev->perf_lock_opts[1] = 0x20E;
4818 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304819
4820 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4821 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004823 adev->platform = platform_init(adev);
4824 if (!adev->platform) {
4825 free(adev->snd_dev_ref_cnt);
4826 free(adev);
4827 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4828 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004829 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304830 pthread_mutex_destroy(&adev->lock);
4831 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004832 return -EINVAL;
4833 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004834
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304835 if (audio_extn_qaf_is_enabled()) {
4836 ret = audio_extn_qaf_init(adev);
4837 if (ret < 0) {
4838 free(adev);
4839 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4840 *device = NULL;
4841 pthread_mutex_unlock(&adev_init_lock);
4842 pthread_mutex_destroy(&adev->lock);
4843 return ret;
4844 }
4845
4846 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4847 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4848 }
4849
Naresh Tanniru4c630392014-05-12 01:05:52 +05304850 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4851
Eric Laurentc4aef752013-09-12 17:45:53 -07004852 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4853 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4854 if (adev->visualizer_lib == NULL) {
4855 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4856 } else {
4857 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4858 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004859 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004860 "visualizer_hal_start_output");
4861 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004862 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004863 "visualizer_hal_stop_output");
4864 }
4865 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004866 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004867 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004868 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004869
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004870 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4871 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4872 if (adev->offload_effects_lib == NULL) {
4873 ALOGE("%s: DLOPEN failed for %s", __func__,
4874 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4875 } else {
4876 ALOGV("%s: DLOPEN successful for %s", __func__,
4877 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4878 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304879 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004880 "offload_effects_bundle_hal_start_output");
4881 adev->offload_effects_stop_output =
4882 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4883 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004884 adev->offload_effects_set_hpx_state =
4885 (int (*)(bool))dlsym(adev->offload_effects_lib,
4886 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304887 adev->offload_effects_get_parameters =
4888 (void (*)(struct str_parms *, struct str_parms *))
4889 dlsym(adev->offload_effects_lib,
4890 "offload_effects_bundle_get_parameters");
4891 adev->offload_effects_set_parameters =
4892 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4893 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004894 }
4895 }
4896
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004897 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4898 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4899 if (adev->adm_lib == NULL) {
4900 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4901 } else {
4902 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4903 adev->adm_init = (adm_init_t)
4904 dlsym(adev->adm_lib, "adm_init");
4905 adev->adm_deinit = (adm_deinit_t)
4906 dlsym(adev->adm_lib, "adm_deinit");
4907 adev->adm_register_input_stream = (adm_register_input_stream_t)
4908 dlsym(adev->adm_lib, "adm_register_input_stream");
4909 adev->adm_register_output_stream = (adm_register_output_stream_t)
4910 dlsym(adev->adm_lib, "adm_register_output_stream");
4911 adev->adm_deregister_stream = (adm_deregister_stream_t)
4912 dlsym(adev->adm_lib, "adm_deregister_stream");
4913 adev->adm_request_focus = (adm_request_focus_t)
4914 dlsym(adev->adm_lib, "adm_request_focus");
4915 adev->adm_abandon_focus = (adm_abandon_focus_t)
4916 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004917 adev->adm_set_config = (adm_set_config_t)
4918 dlsym(adev->adm_lib, "adm_set_config");
4919 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4920 dlsym(adev->adm_lib, "adm_request_focus_v2");
4921 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4922 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4923 adev->adm_on_routing_change = (adm_on_routing_change_t)
4924 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004925 }
4926 }
4927
Mingming Yin514a8bc2014-07-29 15:22:21 -07004928 adev->bt_wb_speech_enabled = false;
4929
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004930 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 *device = &adev->device.common;
4932
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004933 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4934 &adev->streams_output_cfg_list);
4935
Kiran Kandi910e1862013-10-29 13:29:42 -07004936 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004937
4938 char value[PROPERTY_VALUE_MAX];
4939 int trial;
4940 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4941 trial = atoi(value);
4942 if (period_size_is_plausible_for_low_latency(trial)) {
4943 pcm_config_low_latency.period_size = trial;
4944 pcm_config_low_latency.start_threshold = trial / 4;
4945 pcm_config_low_latency.avail_min = trial / 4;
4946 configured_low_latency_capture_period_size = trial;
4947 }
4948 }
4949 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4950 trial = atoi(value);
4951 if (period_size_is_plausible_for_low_latency(trial)) {
4952 configured_low_latency_capture_period_size = trial;
4953 }
4954 }
4955
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004956 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4957 af_period_multiplier = atoi(value);
4958 if (af_period_multiplier < 0)
4959 af_period_multiplier = 2;
4960 else if (af_period_multiplier > 4)
4961 af_period_multiplier = 4;
4962
4963 ALOGV("new period_multiplier = %d", af_period_multiplier);
4964 }
4965
vivek mehta446c3962015-09-14 10:57:35 -07004966 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004967 pthread_mutex_unlock(&adev_init_lock);
4968
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004969 if (adev->adm_init)
4970 adev->adm_data = adev->adm_init();
4971
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304972 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004973 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974 return 0;
4975}
4976
4977static struct hw_module_methods_t hal_module_methods = {
4978 .open = adev_open,
4979};
4980
4981struct audio_module HAL_MODULE_INFO_SYM = {
4982 .common = {
4983 .tag = HARDWARE_MODULE_TAG,
4984 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4985 .hal_api_version = HARDWARE_HAL_API_VERSION,
4986 .id = AUDIO_HARDWARE_MODULE_ID,
4987 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004988 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989 .methods = &hal_module_methods,
4990 },
4991};