blob: 134ddb14603c3cec6087141c9537d907ca325d89 [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",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530499 format == AUDIO_FORMAT_AAC_LC ||
500 format == AUDIO_FORMAT_AAC_HE_V1 ||
501 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530502 format == AUDIO_FORMAT_AAC_ADTS_LC ||
503 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530505 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
506 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530507 format == AUDIO_FORMAT_PCM_FLOAT ||
508 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700509 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530510 format == AUDIO_FORMAT_AC3 ||
511 format == AUDIO_FORMAT_E_AC3 ||
512 format == AUDIO_FORMAT_DTS ||
513 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800514 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530515 format == AUDIO_FORMAT_ALAC ||
516 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530517 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530518 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800519 format == AUDIO_FORMAT_WMA ||
520 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800521 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700522
523 return false;
524}
525
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700526static inline bool is_mmap_usecase(audio_usecase_t uc_id)
527{
528 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
529 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
530}
531
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530532int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530533{
534 int snd_scard_state;
535
536 if (!adev)
537 return SND_CARD_STATE_OFFLINE;
538
539 pthread_mutex_lock(&adev->snd_card_status.lock);
540 snd_scard_state = adev->snd_card_status.state;
541 pthread_mutex_unlock(&adev->snd_card_status.lock);
542
543 return snd_scard_state;
544}
545
546static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
547{
548 if (!adev)
549 return -ENOSYS;
550
551 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700552 if (adev->snd_card_status.state != snd_scard_state) {
553 adev->snd_card_status.state = snd_scard_state;
554 platform_snd_card_update(adev->platform, snd_scard_state);
555 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530556 pthread_mutex_unlock(&adev->snd_card_status.lock);
557
558 return 0;
559}
560
Avinash Vaish71a8b972014-07-24 15:36:33 +0530561static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
562 struct audio_usecase *uc_info)
563{
564 struct listnode *node;
565 struct audio_usecase *usecase;
566
567 if (uc_info == NULL)
568 return -EINVAL;
569
570 /* Re-route all voice usecases on the shared backend other than the
571 specified usecase to new snd devices */
572 list_for_each(node, &adev->usecase_list) {
573 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800574 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530575 enable_audio_route(adev, usecase);
576 }
577 return 0;
578}
579
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530580static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530581{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530582 ALOGV("%s", __func__);
583 audio_route_apply_and_update_path(adev->audio_route,
584 "asrc-mode");
585 adev->asrc_mode_enabled = true;
586}
587
588static void disable_asrc_mode(struct audio_device *adev)
589{
590 ALOGV("%s", __func__);
591 audio_route_reset_and_update_path(adev->audio_route,
592 "asrc-mode");
593 adev->asrc_mode_enabled = false;
594}
595
596/*
597 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
598 * 44.1 or Native DSD backends are enabled for any of current use case.
599 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
600 * - Disable current mix path use case(Headphone backend) and re-enable it with
601 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
602 * e.g. Naitve DSD or Headphone 44.1 -> + 48
603 */
604static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
605{
606 ALOGV("%s snd device %d", __func__, snd_device);
607 int new_backend_idx = platform_get_backend_index(snd_device);
608
609 if (((new_backend_idx == HEADPHONE_BACKEND) ||
610 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
611 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
612 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613 struct listnode *node = NULL;
614 struct audio_usecase *uc = NULL;
615 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530616 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530617
618 list_for_each(node, &adev->usecase_list) {
619 uc = node_to_item(node, struct audio_usecase, list);
620 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530621 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530622 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
623
624 if((new_backend_idx == HEADPHONE_BACKEND) &&
625 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
626 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530627 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
628 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530629 enable_asrc_mode(adev);
630 break;
631 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
632 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
633 (usecase_backend_idx == HEADPHONE_BACKEND)) {
634 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
635 __func__);
636 disable_audio_route(adev, uc);
637 disable_snd_device(adev, uc->out_snd_device);
638 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
639 if (new_backend_idx == DSD_NATIVE_BACKEND)
640 audio_route_apply_and_update_path(adev->audio_route,
641 "hph-true-highquality-mode");
642 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
643 (curr_out->bit_width >= 24))
644 audio_route_apply_and_update_path(adev->audio_route,
645 "hph-highquality-mode");
646 enable_asrc_mode(adev);
647 enable_snd_device(adev, uc->out_snd_device);
648 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649 break;
650 }
651 }
652 }
653 }
654}
655
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700656int pcm_ioctl(struct pcm *pcm, int request, ...)
657{
658 va_list ap;
659 void * arg;
660 int pcm_fd = *(int*)pcm;
661
662 va_start(ap, request);
663 arg = va_arg(ap, void *);
664 va_end(ap);
665
666 return ioctl(pcm_fd, request, arg);
667}
668
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700669int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700670 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700673 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800674
675 if (usecase == NULL)
676 return -EINVAL;
677
678 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
679
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800680 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800682 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800684
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800685#ifdef DS1_DOLBY_DAP_ENABLED
686 audio_extn_dolby_set_dmid(adev);
687 audio_extn_dolby_set_endpoint(adev);
688#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700689 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700690 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530691 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700692 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530693 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800694 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700695 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700696 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700697 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698 ALOGV("%s: exit", __func__);
699 return 0;
700}
701
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700702int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700703 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700706 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800707
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530708 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800709 return -EINVAL;
710
711 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 if (usecase->type == PCM_CAPTURE)
713 snd_device = usecase->in_snd_device;
714 else
715 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800716 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700717 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700718 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700719 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700720 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530721 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 ALOGV("%s: exit", __func__);
723 return 0;
724}
725
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700726int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530729 int i, num_devices = 0;
730 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700731 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
732
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 if (snd_device < SND_DEVICE_MIN ||
734 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800735 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800736 return -EINVAL;
737 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700738
739 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700740
741 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
742 ALOGE("%s: Invalid sound device returned", __func__);
743 return -EINVAL;
744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700746 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700747 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700748 return 0;
749 }
750
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530751
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700752 if (audio_extn_spkr_prot_is_enabled())
753 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700754
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800755 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
756 audio_extn_spkr_prot_is_enabled()) {
757 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700758 adev->snd_dev_ref_cnt[snd_device]--;
759 return -EINVAL;
760 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200761 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800762 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800763 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200764 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800765 return -EINVAL;
766 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700767 } else if (platform_split_snd_device(adev->platform,
768 snd_device,
769 &num_devices,
770 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530771 for (i = 0; i < num_devices; i++) {
772 enable_snd_device(adev, new_snd_devices[i]);
773 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800774 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700775 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530776
777 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
778 (audio_extn_a2dp_start_playback() < 0)) {
779 ALOGE(" fail to configure A2dp control path ");
780 return -EINVAL;
781 }
782
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700783 /* due to the possibility of calibration overwrite between listen
784 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700785 audio_extn_sound_trigger_update_device_status(snd_device,
786 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530787 audio_extn_listen_update_device_status(snd_device,
788 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700789 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700791 audio_extn_sound_trigger_update_device_status(snd_device,
792 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530793 audio_extn_listen_update_device_status(snd_device,
794 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700795 return -EINVAL;
796 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300797 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700798 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530799
800 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
801 !adev->native_playback_enabled &&
802 audio_is_true_native_stream_active(adev)) {
803 ALOGD("%s: %d: napb: enabling native mode in hardware",
804 __func__, __LINE__);
805 audio_route_apply_and_update_path(adev->audio_route,
806 "true-native-mode");
807 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530808 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810 return 0;
811}
812
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700813int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700814 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530816 int i, num_devices = 0;
817 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700818 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
819
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800820 if (snd_device < SND_DEVICE_MIN ||
821 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800822 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800823 return -EINVAL;
824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
826 ALOGE("%s: device ref cnt is already 0", __func__);
827 return -EINVAL;
828 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700829
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700831
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700832 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
833 ALOGE("%s: Invalid sound device returned", __func__);
834 return -EINVAL;
835 }
836
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700838 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530839
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800840 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
841 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700842 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700843 } else if (platform_split_snd_device(adev->platform,
844 snd_device,
845 &num_devices,
846 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530847 for (i = 0; i < num_devices; i++) {
848 disable_snd_device(adev, new_snd_devices[i]);
849 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300850 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700851 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300852 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700853
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530854 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
855 audio_extn_a2dp_stop_playback();
856
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700857 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530858 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530859 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
860 adev->native_playback_enabled) {
861 ALOGD("%s: %d: napb: disabling native mode in hardware",
862 __func__, __LINE__);
863 audio_route_reset_and_update_path(adev->audio_route,
864 "true-native-mode");
865 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530866 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
867 adev->asrc_mode_enabled) {
868 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530869 disable_asrc_mode(adev);
870 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530871 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530872
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200873 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700874 audio_extn_sound_trigger_update_device_status(snd_device,
875 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530876 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800877 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800880 return 0;
881}
882
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700883/*
884 legend:
885 uc - existing usecase
886 new_uc - new usecase
887 d1, d11, d2 - SND_DEVICE enums
888 a1, a2 - corresponding ANDROID device enums
889 B1, B2 - backend strings
890
891case 1
892 uc->dev d1 (a1) B1
893 new_uc->dev d1 (a1), d2 (a2) B1, B2
894
895 resolution: disable and enable uc->dev on d1
896
897case 2
898 uc->dev d1 (a1) B1
899 new_uc->dev d11 (a1) B1
900
901 resolution: need to switch uc since d1 and d11 are related
902 (e.g. speaker and voice-speaker)
903 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
904
905case 3
906 uc->dev d1 (a1) B1
907 new_uc->dev d2 (a2) B2
908
909 resolution: no need to switch uc
910
911case 4
912 uc->dev d1 (a1) B1
913 new_uc->dev d2 (a2) B1
914
915 resolution: disable enable uc-dev on d2 since backends match
916 we cannot enable two streams on two different devices if they
917 share the same backend. e.g. if offload is on speaker device using
918 QUAD_MI2S backend and a low-latency stream is started on voice-handset
919 using the same backend, offload must also be switched to voice-handset.
920
921case 5
922 uc->dev d1 (a1) B1
923 new_uc->dev d1 (a1), d2 (a2) B1
924
925 resolution: disable enable uc-dev on d2 since backends match
926 we cannot enable two streams on two different devices if they
927 share the same backend.
928
929case 6
930 uc->dev d1 (a1) B1
931 new_uc->dev d2 (a1) B2
932
933 resolution: no need to switch
934
935case 7
936 uc->dev d1 (a1), d2 (a2) B1, B2
937 new_uc->dev d1 (a1) B1
938
939 resolution: no need to switch
940
941*/
942static snd_device_t derive_playback_snd_device(void * platform,
943 struct audio_usecase *uc,
944 struct audio_usecase *new_uc,
945 snd_device_t new_snd_device)
946{
947 audio_devices_t a1 = uc->stream.out->devices;
948 audio_devices_t a2 = new_uc->stream.out->devices;
949
950 snd_device_t d1 = uc->out_snd_device;
951 snd_device_t d2 = new_snd_device;
952
953 // Treat as a special case when a1 and a2 are not disjoint
954 if ((a1 != a2) && (a1 & a2)) {
955 snd_device_t d3[2];
956 int num_devices = 0;
957 int ret = platform_split_snd_device(platform,
958 popcount(a1) > 1 ? d1 : d2,
959 &num_devices,
960 d3);
961 if (ret < 0) {
962 if (ret != -ENOSYS) {
963 ALOGW("%s failed to split snd_device %d",
964 __func__,
965 popcount(a1) > 1 ? d1 : d2);
966 }
967 goto end;
968 }
969
970 // NB: case 7 is hypothetical and isn't a practical usecase yet.
971 // But if it does happen, we need to give priority to d2 if
972 // the combo devices active on the existing usecase share a backend.
973 // This is because we cannot have a usecase active on a combo device
974 // and a new usecase requests one device in this combo pair.
975 if (platform_check_backends_match(d3[0], d3[1])) {
976 return d2; // case 5
977 } else {
978 return d1; // case 1
979 }
980 } else {
981 if (platform_check_backends_match(d1, d2)) {
982 return d2; // case 2, 4
983 } else {
984 return d1; // case 6, 3
985 }
986 }
987
988end:
989 return d2; // return whatever was calculated before.
990}
991
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700992static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700995{
996 struct listnode *node;
997 struct audio_usecase *usecase;
998 bool switch_device[AUDIO_USECASE_MAX];
999 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301000 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 /*
1002 * This function is to make sure that all the usecases that are active on
1003 * the hardware codec backend are always routed to any one device that is
1004 * handled by the hardware codec.
1005 * For example, if low-latency and deep-buffer usecases are currently active
1006 * on speaker and out_set_parameters(headset) is received on low-latency
1007 * output, then we have to make sure deep-buffer is also switched to headset,
1008 * because of the limitation that both the devices cannot be enabled
1009 * at the same time as they share the same backend.
1010 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001011 /*
1012 * This call is to check if we need to force routing for a particular stream
1013 * If there is a backend configuration change for the device when a
1014 * new stream starts, then ADM needs to be closed and re-opened with the new
1015 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001016 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001017 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001018 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1019 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301020 /* For a2dp device reconfigure all active sessions
1021 * with new AFE encoder format based on a2dp state
1022 */
1023 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1024 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1025 audio_extn_a2dp_is_force_device_switch()) {
1026 force_routing = true;
1027 force_restart_session = true;
1028 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301029 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1030
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001032 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001033 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1035 switch_device[i] = false;
1036
1037 list_for_each(node, &adev->usecase_list) {
1038 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001039
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301040 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1041 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301042 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301043 platform_get_snd_device_name(usecase->out_snd_device),
1044 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001045 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301046 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001047 (derive_playback_snd_device(adev->platform,
1048 usecase, uc_info,
1049 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301050 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1051 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301052 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301053 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301054 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
1055
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301056 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1057 __func__, use_case_table[usecase->id],
1058 platform_get_snd_device_name(usecase->out_snd_device));
1059 disable_audio_route(adev, usecase);
1060 switch_device[usecase->id] = true;
1061 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 }
1063 }
1064
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301065 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1066 num_uc_to_switch);
1067
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001069 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301071 /* Make sure the previous devices to be disabled first and then enable the
1072 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 list_for_each(node, &adev->usecase_list) {
1074 usecase = node_to_item(node, struct audio_usecase, list);
1075 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001076 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 }
1078 }
1079
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001080 list_for_each(node, &adev->usecase_list) {
1081 usecase = node_to_item(node, struct audio_usecase, list);
1082 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001083 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001084 }
1085 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 /* Re-route all the usecases on the shared backend other than the
1088 specified usecase to new snd devices */
1089 list_for_each(node, &adev->usecase_list) {
1090 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301091 /* Update the out_snd_device only before enabling the audio route */
1092 if (switch_device[usecase->id]) {
1093 usecase->out_snd_device = snd_device;
1094 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301096 use_case_table[usecase->id],
1097 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301098 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301099 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 }
1101 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 }
1103}
1104
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301105static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001106 struct audio_usecase *uc_info,
1107 snd_device_t snd_device)
1108{
1109 struct listnode *node;
1110 struct audio_usecase *usecase;
1111 bool switch_device[AUDIO_USECASE_MAX];
1112 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301113 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001114
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301115 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1116 snd_device);
1117 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301118
1119 /*
1120 * Make sure out devices is checked against out codec backend device and
1121 * also in devices against in codec backend. Checking out device against in
1122 * codec backend or vice versa causes issues.
1123 */
1124 if (uc_info->type == PCM_CAPTURE)
1125 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001126 /*
1127 * This function is to make sure that all the active capture usecases
1128 * are always routed to the same input sound device.
1129 * For example, if audio-record and voice-call usecases are currently
1130 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1131 * is received for voice call then we have to make sure that audio-record
1132 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1133 * because of the limitation that two devices cannot be enabled
1134 * at the same time if they share the same backend.
1135 */
1136 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1137 switch_device[i] = false;
1138
1139 list_for_each(node, &adev->usecase_list) {
1140 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301141 /*
1142 * TODO: Enhance below condition to handle BT sco/USB multi recording
1143 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001144 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001145 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301146 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301147 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301148 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001149 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001150 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001151 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1152 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001153 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001154 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001155 switch_device[usecase->id] = true;
1156 num_uc_to_switch++;
1157 }
1158 }
1159
1160 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001161 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301163 /* Make sure the previous devices to be disabled first and then enable the
1164 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 list_for_each(node, &adev->usecase_list) {
1166 usecase = node_to_item(node, struct audio_usecase, list);
1167 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001168 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001169 }
1170 }
1171
1172 list_for_each(node, &adev->usecase_list) {
1173 usecase = node_to_item(node, struct audio_usecase, list);
1174 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001175 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001176 }
1177 }
1178
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179 /* Re-route all the usecases on the shared backend other than the
1180 specified usecase to new snd devices */
1181 list_for_each(node, &adev->usecase_list) {
1182 usecase = node_to_item(node, struct audio_usecase, list);
1183 /* Update the in_snd_device only before enabling the audio route */
1184 if (switch_device[usecase->id] ) {
1185 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001186 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301187 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001188 }
1189 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001190 }
1191}
1192
Mingming Yin3a941d42016-02-17 18:08:05 -08001193static void reset_hdmi_sink_caps(struct stream_out *out) {
1194 int i = 0;
1195
1196 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1197 out->supported_channel_masks[i] = 0;
1198 }
1199 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1200 out->supported_formats[i] = 0;
1201 }
1202 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1203 out->supported_sample_rates[i] = 0;
1204 }
1205}
1206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001208static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209{
Mingming Yin3a941d42016-02-17 18:08:05 -08001210 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001211 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212
Mingming Yin3a941d42016-02-17 18:08:05 -08001213 reset_hdmi_sink_caps(out);
1214
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001215 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001216 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001217 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001218 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001219 }
1220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001223 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001224 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001225 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1226 case 6:
1227 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1228 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1229 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1230 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1231 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1232 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233 break;
1234 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001235 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001236 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 break;
1238 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001239
1240 // check channel format caps
1241 i = 0;
1242 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1243 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1244 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1245 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1246 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1247 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1248 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1249 }
1250
1251 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1252 ALOGV(":%s HDMI supports DTS format", __func__);
1253 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1254 }
1255
1256 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1257 ALOGV(":%s HDMI supports DTS HD format", __func__);
1258 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1259 }
1260
1261
1262 // check sample rate caps
1263 i = 0;
1264 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1265 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1266 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1267 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1268 }
1269 }
1270
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001271 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272}
1273
Alexy Josephb1379942016-01-29 15:49:38 -08001274audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001275 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001276{
1277 struct audio_usecase *usecase;
1278 struct listnode *node;
1279
1280 list_for_each(node, &adev->usecase_list) {
1281 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001282 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001283 ALOGV("%s: usecase id %d", __func__, usecase->id);
1284 return usecase->id;
1285 }
1286 }
1287 return USECASE_INVALID;
1288}
1289
Alexy Josephb1379942016-01-29 15:49:38 -08001290struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001291 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292{
1293 struct audio_usecase *usecase;
1294 struct listnode *node;
1295
1296 list_for_each(node, &adev->usecase_list) {
1297 usecase = node_to_item(node, struct audio_usecase, list);
1298 if (usecase->id == uc_id)
1299 return usecase;
1300 }
1301 return NULL;
1302}
1303
Dhananjay Kumard4833242016-10-06 22:09:12 +05301304struct stream_in *get_next_active_input(const struct audio_device *adev)
1305{
1306 struct audio_usecase *usecase;
1307 struct listnode *node;
1308
1309 list_for_each_reverse(node, &adev->usecase_list) {
1310 usecase = node_to_item(node, struct audio_usecase, list);
1311 if (usecase->type == PCM_CAPTURE)
1312 return usecase->stream.in;
1313 }
1314 return NULL;
1315}
1316
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301317/*
1318 * is a true native playback active
1319 */
1320bool audio_is_true_native_stream_active(struct audio_device *adev)
1321{
1322 bool active = false;
1323 int i = 0;
1324 struct listnode *node;
1325
1326 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1327 ALOGV("%s:napb: not in true mode or non hdphones device",
1328 __func__);
1329 active = false;
1330 goto exit;
1331 }
1332
1333 list_for_each(node, &adev->usecase_list) {
1334 struct audio_usecase *uc;
1335 uc = node_to_item(node, struct audio_usecase, list);
1336 struct stream_out *curr_out =
1337 (struct stream_out*) uc->stream.out;
1338
1339 if (curr_out && PCM_PLAYBACK == uc->type) {
1340 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1341 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1342 uc->id, curr_out->sample_rate,
1343 curr_out->bit_width,
1344 platform_get_snd_device_name(uc->out_snd_device));
1345
1346 if (is_offload_usecase(uc->id) &&
1347 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1348 active = true;
1349 ALOGD("%s:napb:native stream detected", __func__);
1350 }
1351 }
1352 }
1353exit:
1354 return active;
1355}
1356
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301357/*
1358 * if native DSD playback active
1359 */
1360bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1361{
1362 bool active = false;
1363 struct listnode *node = NULL;
1364 struct audio_usecase *uc = NULL;
1365 struct stream_out *curr_out = NULL;
1366
1367 list_for_each(node, &adev->usecase_list) {
1368 uc = node_to_item(node, struct audio_usecase, list);
1369 curr_out = (struct stream_out*) uc->stream.out;
1370
1371 if (curr_out && PCM_PLAYBACK == uc->type &&
1372 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1373 active = true;
1374 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301375 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301376 }
1377 }
1378 return active;
1379}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301380
1381static bool force_device_switch(struct audio_usecase *usecase)
1382{
1383 bool ret = false;
1384 bool is_it_true_mode = false;
1385
1386 if (is_offload_usecase(usecase->id) &&
1387 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001388 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1389 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1390 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301391 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1392 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1393 (!is_it_true_mode && adev->native_playback_enabled)){
1394 ret = true;
1395 ALOGD("napb: time to toggle native mode");
1396 }
1397 }
1398
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301399 // Force all a2dp output devices to reconfigure for proper AFE encode format
1400 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001401 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301402 audio_extn_a2dp_is_force_device_switch()) {
1403 ALOGD("Force a2dp device switch to update new encoder config");
1404 ret = true;
1405 }
1406
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301407 return ret;
1408}
1409
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001410int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001412 snd_device_t out_snd_device = SND_DEVICE_NONE;
1413 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 struct audio_usecase *usecase = NULL;
1415 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001416 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001417 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001418 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001419 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1422
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001423 usecase = get_usecase_from_list(adev, uc_id);
1424 if (usecase == NULL) {
1425 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1426 return -EINVAL;
1427 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001429 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001430 (usecase->type == VOIP_CALL) ||
1431 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301432 if(usecase->stream.out == NULL) {
1433 ALOGE("%s: stream.out is NULL", __func__);
1434 return -EINVAL;
1435 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001436 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001437 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001438 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 usecase->devices = usecase->stream.out->devices;
1440 } else {
1441 /*
1442 * If the voice call is active, use the sound devices of voice call usecase
1443 * so that it would not result any device switch. All the usecases will
1444 * be switched to new device when select_devices() is called for voice call
1445 * usecase. This is to avoid switching devices for voice call when
1446 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001447 * choose voice call device only if the use case device is
1448 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001450 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001451 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001452 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001453 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1454 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301455 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1456 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001457 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 in_snd_device = vc_usecase->in_snd_device;
1459 out_snd_device = vc_usecase->out_snd_device;
1460 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001461 } else if (voice_extn_compress_voip_is_active(adev)) {
1462 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001463 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001464 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1465 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001466 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001467 in_snd_device = voip_usecase->in_snd_device;
1468 out_snd_device = voip_usecase->out_snd_device;
1469 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001470 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001471 hfp_ucid = audio_extn_hfp_get_usecase();
1472 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001473 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001474 in_snd_device = hfp_usecase->in_snd_device;
1475 out_snd_device = hfp_usecase->out_snd_device;
1476 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 }
1478 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301479 if (usecase->stream.out == NULL) {
1480 ALOGE("%s: stream.out is NULL", __func__);
1481 return -EINVAL;
1482 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 usecase->devices = usecase->stream.out->devices;
1484 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001485 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001486 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001487 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001488 if (usecase->stream.out == adev->primary_output &&
1489 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001490 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001491 select_devices(adev, adev->active_input->usecase);
1492 }
1493 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301495 if (usecase->stream.in == NULL) {
1496 ALOGE("%s: stream.in is NULL", __func__);
1497 return -EINVAL;
1498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 usecase->devices = usecase->stream.in->device;
1500 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001501 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001502 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001503 if (adev->active_input &&
1504 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301505 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1506 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1507 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001508 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001509 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001510 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1511 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001512 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001513 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001514 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 }
1516 }
1517
1518 if (out_snd_device == usecase->out_snd_device &&
1519 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301520
1521 if (!force_device_switch(usecase))
1522 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 }
1524
sangwoobc677242013-08-08 16:53:43 +09001525 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001526 out_snd_device, platform_get_snd_device_name(out_snd_device),
1527 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 /*
1530 * Limitation: While in call, to do a device switch we need to disable
1531 * and enable both RX and TX devices though one of them is same as current
1532 * device.
1533 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001534 if ((usecase->type == VOICE_CALL) &&
1535 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1536 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001537 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001538 }
1539
1540 if (((usecase->type == VOICE_CALL) ||
1541 (usecase->type == VOIP_CALL)) &&
1542 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1543 /* Disable sidetone only if voice/voip call already exists */
1544 if (voice_is_call_state_active(adev) ||
1545 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001546 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001547
1548 /* Disable aanc only if voice call exists */
1549 if (voice_is_call_state_active(adev))
1550 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001551 }
1552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 /* Disable current sound devices */
1554 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001555 disable_audio_route(adev, usecase);
1556 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557 }
1558
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001560 disable_audio_route(adev, usecase);
1561 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 }
1563
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001564 /* Applicable only on the targets that has external modem.
1565 * New device information should be sent to modem before enabling
1566 * the devices to reduce in-call device switch time.
1567 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001568 if ((usecase->type == VOICE_CALL) &&
1569 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1570 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001571 status = platform_switch_voice_call_enable_device_config(adev->platform,
1572 out_snd_device,
1573 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001574 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576 /* Enable new sound devices */
1577 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001578 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301579 if (platform_check_codec_asrc_support(adev->platform))
1580 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001581 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001584 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301585 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001586 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588
Avinash Vaish71a8b972014-07-24 15:36:33 +05301589 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001590 status = platform_switch_voice_call_device_post(adev->platform,
1591 out_snd_device,
1592 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301593 enable_audio_route_for_voice_usecases(adev, usecase);
1594 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001595
sangwoo170731f2013-06-08 15:36:36 +09001596 usecase->in_snd_device = in_snd_device;
1597 usecase->out_snd_device = out_snd_device;
1598
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301599 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1600 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301601 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001602 if ((24 == usecase->stream.out->bit_width) &&
1603 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1604 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1605 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1606 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1607 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1608 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1609 /*
1610 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1611 * configured device sample rate, if not update the COPP rate to be equal to the
1612 * device sample rate, else open COPP at stream sample rate
1613 */
1614 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1615 usecase->stream.out->sample_rate,
1616 &usecase->stream.out->app_type_cfg.sample_rate);
1617 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1618 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1619 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1620 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1621 }
1622
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001623 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001624 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001625 audio_extn_gef_notify_device_config(
1626 usecase->stream.out->devices,
1627 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001628 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001629 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001630 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301631 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001632 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001633
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001634 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001635 /* Enable aanc only if voice call exists */
1636 if (voice_is_call_state_active(adev))
1637 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1638
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001639 /* Enable sidetone only if other voice/voip call already exists */
1640 if (voice_is_call_state_active(adev) ||
1641 voice_extn_compress_voip_is_started(adev))
1642 voice_set_sidetone(adev, out_snd_device, true);
1643 }
1644
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001645 /* Applicable only on the targets that has external modem.
1646 * Enable device command should be sent to modem only after
1647 * enabling voice call mixer controls
1648 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001649 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001650 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1651 out_snd_device,
1652 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301653 ALOGD("%s: done",__func__);
1654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 return status;
1656}
1657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658static int stop_input_stream(struct stream_in *in)
1659{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301660 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 struct audio_usecase *uc_info;
1662 struct audio_device *adev = in->dev;
1663
Dhananjay Kumard4833242016-10-06 22:09:12 +05301664 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665
Eric Laurent994a6932013-07-17 11:51:42 -07001666 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668 uc_info = get_usecase_from_list(adev, in->usecase);
1669 if (uc_info == NULL) {
1670 ALOGE("%s: Could not find the usecase (%d) in the list",
1671 __func__, in->usecase);
1672 return -EINVAL;
1673 }
1674
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001675 /* Close in-call recording streams */
1676 voice_check_and_stop_incall_rec_usecase(adev, in);
1677
Eric Laurent150dbfe2013-02-27 14:31:02 -08001678 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001679 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001680
1681 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001682 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001684 list_remove(&uc_info->list);
1685 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
Eric Laurent994a6932013-07-17 11:51:42 -07001687 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 return ret;
1689}
1690
1691int start_input_stream(struct stream_in *in)
1692{
1693 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001694 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 struct audio_usecase *uc_info;
1696 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301697 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698
Mingming Yin2664a5b2015-09-03 10:53:11 -07001699 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1700 if (get_usecase_from_list(adev, usecase) == NULL)
1701 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301702 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1703 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001704
Naresh Tanniru80659832014-06-04 18:17:56 +05301705
1706 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301707 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301708 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301709 goto error_config;
1710 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301711
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001712 /* Check if source matches incall recording usecase criteria */
1713 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1714 if (ret)
1715 goto error_config;
1716 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001717 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1718
1719 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1720 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1721 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001722 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001723 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001724
Eric Laurentb23d5282013-05-14 15:27:20 -07001725 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726 if (in->pcm_device_id < 0) {
1727 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1728 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001729 ret = -EINVAL;
1730 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001732
1733 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001735
1736 if (!uc_info) {
1737 ret = -ENOMEM;
1738 goto error_config;
1739 }
1740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 uc_info->id = in->usecase;
1742 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001743 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001744 uc_info->devices = in->device;
1745 uc_info->in_snd_device = SND_DEVICE_NONE;
1746 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001748 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301749 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1750 adev->perf_lock_opts,
1751 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301754 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1755 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001756
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301757 if (audio_extn_cin_attached_usecase(in->usecase)) {
1758 ret = audio_extn_cin_start_input_stream(in);
1759 if (ret)
1760 goto error_open;
1761 else
1762 goto done_open;
1763 }
1764
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001765 unsigned int flags = PCM_IN;
1766 unsigned int pcm_open_retry_count = 0;
1767
1768 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1769 flags |= PCM_MMAP | PCM_NOIRQ;
1770 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001771 } else if (in->realtime) {
1772 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001773 }
1774
1775 while (1) {
1776 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1777 flags, &in->config);
1778 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1779 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1780 if (in->pcm != NULL) {
1781 pcm_close(in->pcm);
1782 in->pcm = NULL;
1783 }
1784 if (pcm_open_retry_count-- == 0) {
1785 ret = -EIO;
1786 goto error_open;
1787 }
1788 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1789 continue;
1790 }
1791 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001793
1794 ALOGV("%s: pcm_prepare", __func__);
1795 ret = pcm_prepare(in->pcm);
1796 if (ret < 0) {
1797 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1798 pcm_close(in->pcm);
1799 in->pcm = NULL;
1800 goto error_open;
1801 }
1802
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001803 register_in_stream(in);
1804 if (in->realtime) {
1805 ret = pcm_start(in->pcm);
1806 if (ret < 0)
1807 goto error_open;
1808 }
1809
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301810done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301811 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001812 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001813
Eric Laurentc8400632013-02-14 19:04:54 -08001814 return ret;
1815
1816error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301817 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001819error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301820 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301821 /*
1822 * sleep 50ms to allow sufficient time for kernel
1823 * drivers to recover incases like SSR.
1824 */
1825 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001827
1828 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829}
1830
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001831void lock_input_stream(struct stream_in *in)
1832{
1833 pthread_mutex_lock(&in->pre_lock);
1834 pthread_mutex_lock(&in->lock);
1835 pthread_mutex_unlock(&in->pre_lock);
1836}
1837
1838void lock_output_stream(struct stream_out *out)
1839{
1840 pthread_mutex_lock(&out->pre_lock);
1841 pthread_mutex_lock(&out->lock);
1842 pthread_mutex_unlock(&out->pre_lock);
1843}
1844
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845/* must be called with out->lock locked */
1846static int send_offload_cmd_l(struct stream_out* out, int command)
1847{
1848 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1849
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001850 if (!cmd) {
1851 ALOGE("failed to allocate mem for command 0x%x", command);
1852 return -ENOMEM;
1853 }
1854
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001855 ALOGVV("%s %d", __func__, command);
1856
1857 cmd->cmd = command;
1858 list_add_tail(&out->offload_cmd_list, &cmd->node);
1859 pthread_cond_signal(&out->offload_cond);
1860 return 0;
1861}
1862
1863/* must be called iwth out->lock locked */
1864static void stop_compressed_output_l(struct stream_out *out)
1865{
1866 out->offload_state = OFFLOAD_STATE_IDLE;
1867 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001868 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869 if (out->compr != NULL) {
1870 compress_stop(out->compr);
1871 while (out->offload_thread_blocked) {
1872 pthread_cond_wait(&out->cond, &out->lock);
1873 }
1874 }
1875}
1876
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001877bool is_offload_usecase(audio_usecase_t uc_id)
1878{
1879 unsigned int i;
1880 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1881 if (uc_id == offload_usecases[i])
1882 return true;
1883 }
1884 return false;
1885}
1886
vivek mehta446c3962015-09-14 10:57:35 -07001887static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001888{
vivek mehta446c3962015-09-14 10:57:35 -07001889 audio_usecase_t ret_uc = USECASE_INVALID;
1890 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001891 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001892 if (!adev->multi_offload_enable) {
1893 if (is_direct_pcm)
1894 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1895 else
1896 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001897
vivek mehta446c3962015-09-14 10:57:35 -07001898 pthread_mutex_lock(&adev->lock);
1899 if (get_usecase_from_list(adev, ret_uc) != NULL)
1900 ret_uc = USECASE_INVALID;
1901 pthread_mutex_unlock(&adev->lock);
1902
1903 return ret_uc;
1904 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001905
1906 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001907 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1908 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1909 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1910 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001911 break;
1912 }
1913 }
vivek mehta446c3962015-09-14 10:57:35 -07001914
1915 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1916 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001917}
1918
1919static void free_offload_usecase(struct audio_device *adev,
1920 audio_usecase_t uc_id)
1921{
vivek mehta446c3962015-09-14 10:57:35 -07001922 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001923 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001924
1925 if (!adev->multi_offload_enable)
1926 return;
1927
1928 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1929 if (offload_usecases[offload_uc_index] == uc_id) {
1930 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001931 break;
1932 }
1933 }
1934 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1935}
1936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001937static void *offload_thread_loop(void *context)
1938{
1939 struct stream_out *out = (struct stream_out *) context;
1940 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001941 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1944 set_sched_policy(0, SP_FOREGROUND);
1945 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1946
1947 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001948 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001949 for (;;) {
1950 struct offload_cmd *cmd = NULL;
1951 stream_callback_event_t event;
1952 bool send_callback = false;
1953
1954 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1955 __func__, list_empty(&out->offload_cmd_list),
1956 out->offload_state);
1957 if (list_empty(&out->offload_cmd_list)) {
1958 ALOGV("%s SLEEPING", __func__);
1959 pthread_cond_wait(&out->offload_cond, &out->lock);
1960 ALOGV("%s RUNNING", __func__);
1961 continue;
1962 }
1963
1964 item = list_head(&out->offload_cmd_list);
1965 cmd = node_to_item(item, struct offload_cmd, node);
1966 list_remove(item);
1967
1968 ALOGVV("%s STATE %d CMD %d out->compr %p",
1969 __func__, out->offload_state, cmd->cmd, out->compr);
1970
1971 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1972 free(cmd);
1973 break;
1974 }
1975
1976 if (out->compr == NULL) {
1977 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001978 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001979 pthread_cond_signal(&out->cond);
1980 continue;
1981 }
1982 out->offload_thread_blocked = true;
1983 pthread_mutex_unlock(&out->lock);
1984 send_callback = false;
1985 switch(cmd->cmd) {
1986 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001987 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001989 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 send_callback = true;
1991 event = STREAM_CBK_EVENT_WRITE_READY;
1992 break;
1993 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001994 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301995 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001996 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301997 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001998 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301999 if (ret < 0)
2000 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302001 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302002 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002003 compress_drain(out->compr);
2004 else
2005 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302006 if (ret != -ENETRESET) {
2007 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302008 pthread_mutex_lock(&out->lock);
2009 out->send_new_metadata = 1;
2010 out->send_next_track_params = true;
2011 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302012 event = STREAM_CBK_EVENT_DRAIN_READY;
2013 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2014 } else
2015 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 break;
2017 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002018 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002020 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021 send_callback = true;
2022 event = STREAM_CBK_EVENT_DRAIN_READY;
2023 break;
2024 default:
2025 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2026 break;
2027 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002028 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 out->offload_thread_blocked = false;
2030 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002031 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002032 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002034 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 free(cmd);
2036 }
2037
2038 pthread_cond_signal(&out->cond);
2039 while (!list_empty(&out->offload_cmd_list)) {
2040 item = list_head(&out->offload_cmd_list);
2041 list_remove(item);
2042 free(node_to_item(item, struct offload_cmd, node));
2043 }
2044 pthread_mutex_unlock(&out->lock);
2045
2046 return NULL;
2047}
2048
2049static int create_offload_callback_thread(struct stream_out *out)
2050{
2051 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2052 list_init(&out->offload_cmd_list);
2053 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2054 offload_thread_loop, out);
2055 return 0;
2056}
2057
2058static int destroy_offload_callback_thread(struct stream_out *out)
2059{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002060 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061 stop_compressed_output_l(out);
2062 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2063
2064 pthread_mutex_unlock(&out->lock);
2065 pthread_join(out->offload_thread, (void **) NULL);
2066 pthread_cond_destroy(&out->offload_cond);
2067
2068 return 0;
2069}
2070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071static int stop_output_stream(struct stream_out *out)
2072{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302073 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 struct audio_usecase *uc_info;
2075 struct audio_device *adev = out->dev;
2076
Eric Laurent994a6932013-07-17 11:51:42 -07002077 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 uc_info = get_usecase_from_list(adev, out->usecase);
2080 if (uc_info == NULL) {
2081 ALOGE("%s: Could not find the usecase (%d) in the list",
2082 __func__, out->usecase);
2083 return -EINVAL;
2084 }
2085
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002086 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302087 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002088 if (adev->visualizer_stop_output != NULL)
2089 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002090
2091 audio_extn_dts_remove_state_notifier_node(out->usecase);
2092
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002093 if (adev->offload_effects_stop_output != NULL)
2094 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2095 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002096
Eric Laurent150dbfe2013-02-27 14:31:02 -08002097 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002098 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099
2100 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002101 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002103 list_remove(&uc_info->list);
2104 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002106 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302107 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002108 ALOGV("Disable passthrough , reset mixer to pcm");
2109 /* NO_PASSTHROUGH */
2110 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002111 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002112 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2113 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002114
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302115 /* Must be called after removing the usecase from list */
2116 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302117 audio_extn_keep_alive_start();
2118
Eric Laurent994a6932013-07-17 11:51:42 -07002119 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 return ret;
2121}
2122
2123int start_output_stream(struct stream_out *out)
2124{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 struct audio_usecase *uc_info;
2127 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002130 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2131 ret = -EINVAL;
2132 goto error_config;
2133 }
2134
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302135 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2136 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2137 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302138
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302140 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302141 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302142 goto error_config;
2143 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302144
Eric Laurentb23d5282013-05-14 15:27:20 -07002145 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 if (out->pcm_device_id < 0) {
2147 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2148 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002149 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002150 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 }
2152
2153 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002154
2155 if (!uc_info) {
2156 ret = -ENOMEM;
2157 goto error_config;
2158 }
2159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 uc_info->id = out->usecase;
2161 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002162 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002163 uc_info->devices = out->devices;
2164 uc_info->in_snd_device = SND_DEVICE_NONE;
2165 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002166 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302168 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2169 adev->perf_lock_opts,
2170 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302171
2172 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2173 audio_extn_keep_alive_stop();
2174 if (audio_extn_passthru_is_enabled() &&
2175 audio_extn_passthru_is_passthrough_stream(out)) {
2176 audio_extn_passthru_on_start(out);
2177 audio_extn_passthru_update_stream_configuration(adev, out);
2178 }
2179 }
2180
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 select_devices(adev, out->usecase);
2182
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002183 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2184 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002185 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002186 unsigned int flags = PCM_OUT;
2187 unsigned int pcm_open_retry_count = 0;
2188 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2189 flags |= PCM_MMAP | PCM_NOIRQ;
2190 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002191 } else if (out->realtime) {
2192 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002193 } else
2194 flags |= PCM_MONOTONIC;
2195
2196 while (1) {
2197 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2198 flags, &out->config);
2199 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2200 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2201 if (out->pcm != NULL) {
2202 pcm_close(out->pcm);
2203 out->pcm = NULL;
2204 }
2205 if (pcm_open_retry_count-- == 0) {
2206 ret = -EIO;
2207 goto error_open;
2208 }
2209 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2210 continue;
2211 }
2212 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002214
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002215 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2216 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002217
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002218 ALOGV("%s: pcm_prepare", __func__);
2219 if (pcm_is_ready(out->pcm)) {
2220 ret = pcm_prepare(out->pcm);
2221 if (ret < 0) {
2222 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2223 pcm_close(out->pcm);
2224 out->pcm = NULL;
2225 goto error_open;
2226 }
2227 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002229 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2230 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002232 out->compr = compress_open(adev->snd_card,
2233 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 COMPRESS_IN, &out->compr_config);
2235 if (out->compr && !is_compress_ready(out->compr)) {
2236 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2237 compress_close(out->compr);
2238 out->compr = NULL;
2239 ret = -EIO;
2240 goto error_open;
2241 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302242 /* compress_open sends params of the track, so reset the flag here */
2243 out->is_compr_metadata_avail = false;
2244
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002245 if (out->offload_callback)
2246 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002247
Fred Oh3f43e742015-03-04 18:42:34 -08002248 /* Since small bufs uses blocking writes, a write will be blocked
2249 for the default max poll time (20s) in the event of an SSR.
2250 Reduce the poll time to observe and deal with SSR faster.
2251 */
Ashish Jain5106d362016-05-11 19:23:33 +05302252 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002253 compress_set_max_poll_wait(out->compr, 1000);
2254 }
2255
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002256 audio_extn_dts_create_state_notifier_node(out->usecase);
2257 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2258 popcount(out->channel_mask),
2259 out->playback_started);
2260
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002261#ifdef DS1_DOLBY_DDP_ENABLED
2262 if (audio_extn_is_dolby_format(out->format))
2263 audio_extn_dolby_send_ddp_endp_params(adev);
2264#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302265 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002266 if (adev->visualizer_start_output != NULL)
2267 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2268 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302269 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002270 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002271 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002273
2274 if (ret == 0) {
2275 register_out_stream(out);
2276 if (out->realtime) {
2277 ret = pcm_start(out->pcm);
2278 if (ret < 0)
2279 goto error_open;
2280 }
2281 }
2282
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302283 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002284 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002285
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002286 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302288 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002290error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302291 /*
2292 * sleep 50ms to allow sufficient time for kernel
2293 * drivers to recover incases like SSR.
2294 */
2295 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002296 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297}
2298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299static int check_input_parameters(uint32_t sample_rate,
2300 audio_format_t format,
2301 int channel_count)
2302{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002303 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302305 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2306 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2307 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002308 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302309 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002310
2311 switch (channel_count) {
2312 case 1:
2313 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302314 case 3:
2315 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002316 case 6:
2317 break;
2318 default:
2319 ret = -EINVAL;
2320 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321
2322 switch (sample_rate) {
2323 case 8000:
2324 case 11025:
2325 case 12000:
2326 case 16000:
2327 case 22050:
2328 case 24000:
2329 case 32000:
2330 case 44100:
2331 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302332 case 96000:
2333 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 break;
2335 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002336 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337 }
2338
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340}
2341
2342static size_t get_input_buffer_size(uint32_t sample_rate,
2343 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002344 int channel_count,
2345 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346{
2347 size_t size = 0;
2348
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002349 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2350 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002352 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002353 if (is_low_latency)
2354 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302355
2356 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002358 /* make sure the size is multiple of 32 bytes
2359 * At 48 kHz mono 16-bit PCM:
2360 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2361 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2362 */
2363 size += 0x1f;
2364 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002365
2366 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367}
2368
Ashish Jain058165c2016-09-28 23:18:48 +05302369static size_t get_output_period_size(uint32_t sample_rate,
2370 audio_format_t format,
2371 int channel_count,
2372 int duration /*in millisecs*/)
2373{
2374 size_t size = 0;
2375 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2376
2377 if ((duration == 0) || (sample_rate == 0) ||
2378 (bytes_per_sample == 0) || (channel_count == 0)) {
2379 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2380 bytes_per_sample, channel_count);
2381 return -EINVAL;
2382 }
2383
2384 size = (sample_rate *
2385 duration *
2386 bytes_per_sample *
2387 channel_count) / 1000;
2388 /*
2389 * To have same PCM samples for all channels, the buffer size requires to
2390 * be multiple of (number of channels * bytes per sample)
2391 * For writes to succeed, the buffer must be written at address which is multiple of 32
2392 */
2393 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2394
2395 return (size/(channel_count * bytes_per_sample));
2396}
2397
Ashish Jain5106d362016-05-11 19:23:33 +05302398static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2399{
2400 uint64_t actual_frames_rendered = 0;
2401 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2402
2403 /* This adjustment accounts for buffering after app processor.
2404 * It is based on estimated DSP latency per use case, rather than exact.
2405 */
2406 int64_t platform_latency = platform_render_latency(out->usecase) *
2407 out->sample_rate / 1000000LL;
2408
2409 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2410 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2411 * hence only estimate.
2412 */
2413 int64_t signed_frames = out->written - kernel_buffer_size;
2414
2415 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2416
2417 if (signed_frames > 0)
2418 actual_frames_rendered = signed_frames;
2419
2420 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2421 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2422 (long long int)out->written, (int)kernel_buffer_size,
2423 audio_bytes_per_sample(out->compr_config.codec->format),
2424 popcount(out->channel_mask));
2425
2426 return actual_frames_rendered;
2427}
2428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2430{
2431 struct stream_out *out = (struct stream_out *)stream;
2432
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434}
2435
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002436static int out_set_sample_rate(struct audio_stream *stream __unused,
2437 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438{
2439 return -ENOSYS;
2440}
2441
2442static size_t out_get_buffer_size(const struct audio_stream *stream)
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
2445
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002446 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002448 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2449 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302450 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302451 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002453 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002454 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455}
2456
2457static uint32_t out_get_channels(const struct audio_stream *stream)
2458{
2459 struct stream_out *out = (struct stream_out *)stream;
2460
2461 return out->channel_mask;
2462}
2463
2464static audio_format_t out_get_format(const struct audio_stream *stream)
2465{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 struct stream_out *out = (struct stream_out *)stream;
2467
2468 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469}
2470
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002471static int out_set_format(struct audio_stream *stream __unused,
2472 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473{
2474 return -ENOSYS;
2475}
2476
2477static int out_standby(struct audio_stream *stream)
2478{
2479 struct stream_out *out = (struct stream_out *)stream;
2480 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002481
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302482 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2483 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002485 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002487 if (adev->adm_deregister_stream)
2488 adev->adm_deregister_stream(adev->adm_data, out->handle);
2489
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002490 if (is_offload_usecase(out->usecase))
2491 stop_compressed_output_l(out);
2492
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002493 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002495 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2496 voice_extn_compress_voip_close_output_stream(stream);
2497 pthread_mutex_unlock(&adev->lock);
2498 pthread_mutex_unlock(&out->lock);
2499 ALOGD("VOIP output entered standby");
2500 return 0;
2501 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 if (out->pcm) {
2503 pcm_close(out->pcm);
2504 out->pcm = NULL;
2505 }
2506 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002507 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302508 out->send_next_track_params = false;
2509 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002510 out->gapless_mdata.encoder_delay = 0;
2511 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002512 if (out->compr != NULL) {
2513 compress_close(out->compr);
2514 out->compr = NULL;
2515 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002518 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 }
2520 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302521 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 return 0;
2523}
2524
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002525static int out_dump(const struct audio_stream *stream __unused,
2526 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527{
2528 return 0;
2529}
2530
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002531static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2532{
2533 int ret = 0;
2534 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002535
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002536 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002537 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002538 return -EINVAL;
2539 }
2540
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302541 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002542
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002543 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2544 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302545 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002546 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002547 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2548 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302549 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002550 }
2551
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002552 ALOGV("%s new encoder delay %u and padding %u", __func__,
2553 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2554
2555 return 0;
2556}
2557
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002558static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2559{
2560 return out == adev->primary_output || out == adev->voice_tx_output;
2561}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566 struct audio_device *adev = out->dev;
2567 struct str_parms *parms;
2568 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002569 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570
sangwoobc677242013-08-08 16:53:43 +09002571 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002572 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302574 if (!parms)
2575 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002576 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2577 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002579 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002580 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002582 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002583 * When HDMI cable is unplugged the music playback is paused and
2584 * the policy manager sends routing=0. But the audioflinger continues
2585 * to write data until standby time (3sec). As the HDMI core is
2586 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002587 * Avoid this by routing audio to speaker until standby.
2588 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002589 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2590 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302591 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002592 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2593 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002594 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302595 /*
2596 * When A2DP is disconnected the
2597 * music playback is paused and the policy manager sends routing=0
2598 * But the audioflingercontinues to write data until standby time
2599 * (3sec). As BT is turned off, the write gets blocked.
2600 * Avoid this by routing audio to speaker until standby.
2601 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002602 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302603 (val == AUDIO_DEVICE_NONE)) {
2604 val = AUDIO_DEVICE_OUT_SPEAKER;
2605 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302606 /* To avoid a2dp to sco overlapping force route BT usecases
2607 * to speaker based on Phone state
2608 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002609 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302610 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2611 (adev->mode == AUDIO_MODE_IN_CALL))) {
2612 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2613 val = AUDIO_DEVICE_OUT_SPEAKER;
2614 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002615 /*
2616 * select_devices() call below switches all the usecases on the same
2617 * backend to the new device. Refer to check_usecases_codec_backend() in
2618 * the select_devices(). But how do we undo this?
2619 *
2620 * For example, music playback is active on headset (deep-buffer usecase)
2621 * and if we go to ringtones and select a ringtone, low-latency usecase
2622 * will be started on headset+speaker. As we can't enable headset+speaker
2623 * and headset devices at the same time, select_devices() switches the music
2624 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2625 * So when the ringtone playback is completed, how do we undo the same?
2626 *
2627 * We are relying on the out_set_parameters() call on deep-buffer output,
2628 * once the ringtone playback is ended.
2629 * NOTE: We should not check if the current devices are same as new devices.
2630 * Because select_devices() must be called to switch back the music
2631 * playback to headset.
2632 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002633 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002634 audio_devices_t new_dev = val;
2635 bool same_dev = out->devices == new_dev;
2636 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002637
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002638 if (output_drives_call(adev, out)) {
2639 if(!voice_is_in_call(adev)) {
2640 if (adev->mode == AUDIO_MODE_IN_CALL) {
2641 adev->current_call_output = out;
2642 ret = voice_start_call(adev);
2643 }
2644 } else {
2645 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002646 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002647 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002648 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002649
2650 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002651 if (!same_dev) {
2652 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302653 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2654 adev->perf_lock_opts,
2655 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002656 if (adev->adm_on_routing_change)
2657 adev->adm_on_routing_change(adev->adm_data,
2658 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002659 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002660 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302661 if (!same_dev)
2662 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002663 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002664 }
2665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002667 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002669
2670 if (out == adev->primary_output) {
2671 pthread_mutex_lock(&adev->lock);
2672 audio_extn_set_parameters(adev, parms);
2673 pthread_mutex_unlock(&adev->lock);
2674 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002675 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002676 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002677 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002678
2679 audio_extn_dts_create_state_notifier_node(out->usecase);
2680 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2681 popcount(out->channel_mask),
2682 out->playback_started);
2683
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002684 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002685 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002686
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302687 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2688 if (err >= 0) {
2689 strlcpy(out->profile, value, sizeof(out->profile));
2690 ALOGV("updating stream profile with value '%s'", out->profile);
2691 lock_output_stream(out);
2692 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2693 &adev->streams_output_cfg_list,
2694 out->devices, out->flags, out->format,
2695 out->sample_rate, out->bit_width,
2696 out->channel_mask, out->profile,
2697 &out->app_type_cfg);
2698 pthread_mutex_unlock(&out->lock);
2699 }
2700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302702error:
Eric Laurent994a6932013-07-17 11:51:42 -07002703 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 return ret;
2705}
2706
2707static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2708{
2709 struct stream_out *out = (struct stream_out *)stream;
2710 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002711 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 char value[256];
2713 struct str_parms *reply = str_parms_create();
2714 size_t i, j;
2715 int ret;
2716 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002717
2718 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002719 if (reply) {
2720 str_parms_destroy(reply);
2721 }
2722 if (query) {
2723 str_parms_destroy(query);
2724 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002725 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2726 return NULL;
2727 }
2728
Eric Laurent994a6932013-07-17 11:51:42 -07002729 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2731 if (ret >= 0) {
2732 value[0] = '\0';
2733 i = 0;
2734 while (out->supported_channel_masks[i] != 0) {
2735 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2736 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2737 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002738 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002740 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 first = false;
2742 break;
2743 }
2744 }
2745 i++;
2746 }
2747 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2748 str = str_parms_to_str(reply);
2749 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002750 voice_extn_out_get_parameters(out, query, reply);
2751 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002752 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002753 free(str);
2754 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002755 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002757
Alexy Joseph62142aa2015-11-16 15:10:34 -08002758
2759 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2760 if (ret >= 0) {
2761 value[0] = '\0';
2762 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2763 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302764 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002765 } else {
2766 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302767 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002768 }
2769 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002770 if (str)
2771 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002772 str = str_parms_to_str(reply);
2773 }
2774
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002775 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2776 if (ret >= 0) {
2777 value[0] = '\0';
2778 i = 0;
2779 first = true;
2780 while (out->supported_formats[i] != 0) {
2781 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2782 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2783 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002784 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002785 }
2786 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2787 first = false;
2788 break;
2789 }
2790 }
2791 i++;
2792 }
2793 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002794 if (str)
2795 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002796 str = str_parms_to_str(reply);
2797 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002798
2799 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2800 if (ret >= 0) {
2801 value[0] = '\0';
2802 i = 0;
2803 first = true;
2804 while (out->supported_sample_rates[i] != 0) {
2805 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2806 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2807 if (!first) {
2808 strlcat(value, "|", sizeof(value));
2809 }
2810 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2811 first = false;
2812 break;
2813 }
2814 }
2815 i++;
2816 }
2817 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2818 if (str)
2819 free(str);
2820 str = str_parms_to_str(reply);
2821 }
2822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 str_parms_destroy(query);
2824 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002825 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 return str;
2827}
2828
2829static uint32_t out_get_latency(const struct audio_stream_out *stream)
2830{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002831 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002833 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834
Alexy Josephaa54c872014-12-03 02:46:47 -08002835 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002836 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002837 } else if (out->realtime) {
2838 // since the buffer won't be filled up faster than realtime,
2839 // return a smaller number
2840 if (out->config.rate)
2841 period_ms = (out->af_period_multiplier * out->config.period_size *
2842 1000) / (out->config.rate);
2843 else
2844 period_ms = 0;
2845 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002846 } else {
2847 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002849 }
2850
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302851 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002852 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853}
2854
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302855static float AmpToDb(float amplification)
2856{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302857 float db = DSD_VOLUME_MIN_DB;
2858 if (amplification > 0) {
2859 db = 20 * log10(amplification);
2860 if(db < DSD_VOLUME_MIN_DB)
2861 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302862 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302863 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302864}
2865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866static int out_set_volume(struct audio_stream_out *stream, float left,
2867 float right)
2868{
Eric Laurenta9024de2013-04-04 09:19:12 -07002869 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 int volume[2];
2871
Eric Laurenta9024de2013-04-04 09:19:12 -07002872 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2873 /* only take left channel into account: the API is for stereo anyway */
2874 out->muted = (left == 0.0f);
2875 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002876 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302877 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002878 /*
2879 * Set mute or umute on HDMI passthrough stream.
2880 * Only take left channel into account.
2881 * Mute is 0 and unmute 1
2882 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302883 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302884 } else if (out->format == AUDIO_FORMAT_DSD){
2885 char mixer_ctl_name[128] = "DSD Volume";
2886 struct audio_device *adev = out->dev;
2887 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2888
2889 if (!ctl) {
2890 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2891 __func__, mixer_ctl_name);
2892 return -EINVAL;
2893 }
2894 volume[0] = (int)(AmpToDb(left));
2895 volume[1] = (int)(AmpToDb(right));
2896 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2897 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002898 } else {
2899 char mixer_ctl_name[128];
2900 struct audio_device *adev = out->dev;
2901 struct mixer_ctl *ctl;
2902 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002903 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002905 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2906 "Compress Playback %d Volume", pcm_device_id);
2907 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2908 if (!ctl) {
2909 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2910 __func__, mixer_ctl_name);
2911 return -EINVAL;
2912 }
2913 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2914 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2915 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2916 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002918 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 return -ENOSYS;
2921}
2922
2923static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2924 size_t bytes)
2925{
2926 struct stream_out *out = (struct stream_out *)stream;
2927 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302928 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002929 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002931 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302932
Naresh Tanniru80659832014-06-04 18:17:56 +05302933 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002934
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302935 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302936 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302937 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2938 pthread_mutex_unlock(&out->lock);
2939 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302940 } else {
2941 /* increase written size during SSR to avoid mismatch
2942 * with the written frames count in AF
2943 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002944 // bytes per frame
2945 size_t bpf = audio_bytes_per_sample(out->format) *
2946 audio_channel_count_from_out_mask(out->channel_mask);
2947 if (bpf != 0)
2948 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302949 ALOGD(" %s: sound card is not active/SSR state", __func__);
2950 ret= -EIO;
2951 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302952 }
2953 }
2954
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302955 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302956 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2957 if (audio_bytes_per_sample(out->format) != 0)
2958 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2959 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302960 goto exit;
2961 }
2962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002964 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002965 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002966 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2967 ret = voice_extn_compress_voip_start_output_stream(out);
2968 else
2969 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002970 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002973 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 goto exit;
2975 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002976
2977 if (last_known_cal_step != -1) {
2978 ALOGD("%s: retry previous failed cal level set", __func__);
2979 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2980 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982
Ashish Jain81eb2a82015-05-13 10:52:34 +05302983 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002984 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302985 adev->is_channel_status_set = true;
2986 }
2987
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002988 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002989 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002990 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002991 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002992 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2993 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302994 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2995 ALOGD("copl(%p):send next track params in gapless", out);
2996 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2997 out->send_next_track_params = false;
2998 out->is_compr_metadata_avail = false;
2999 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003000 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303001 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303002 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003003
Ashish Jain83a6cc22016-06-28 14:34:17 +05303004 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303005 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303006 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303007 pthread_mutex_unlock(&out->lock);
3008 return -EINVAL;
3009 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303010 audio_format_t dst_format = out->hal_op_format;
3011 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303012
3013 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3014 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3015
Ashish Jain83a6cc22016-06-28 14:34:17 +05303016 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303017 dst_format,
3018 buffer,
3019 src_format,
3020 frames);
3021
Ashish Jain83a6cc22016-06-28 14:34:17 +05303022 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303023 bytes_to_write);
3024
3025 /*Convert written bytes in audio flinger format*/
3026 if (ret > 0)
3027 ret = ((ret * format_to_bitwidth_table[out->format]) /
3028 format_to_bitwidth_table[dst_format]);
3029 }
3030 } else
3031 ret = compress_write(out->compr, buffer, bytes);
3032
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303033 if (ret < 0)
3034 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303035 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303036 /*msg to cb thread only if non blocking write is enabled*/
3037 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303038 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303040 } else if (-ENETRESET == ret) {
3041 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3042 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3043 pthread_mutex_unlock(&out->lock);
3044 out_standby(&out->stream.common);
3045 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 }
Ashish Jain5106d362016-05-11 19:23:33 +05303047 if ( ret == (ssize_t)bytes && !out->non_blocking)
3048 out->written += bytes;
3049
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303050 /* Call compr start only when non-zero bytes of data is there to be rendered */
3051 if (!out->playback_started && ret > 0) {
3052 int status = compress_start(out->compr);
3053 if (status < 0) {
3054 ret = status;
3055 ALOGE("%s: compr start failed with err %d", __func__, errno);
3056 goto exit;
3057 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003058 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 out->playback_started = 1;
3060 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003061
3062 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3063 popcount(out->channel_mask),
3064 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 }
3066 pthread_mutex_unlock(&out->lock);
3067 return ret;
3068 } else {
3069 if (out->pcm) {
3070 if (out->muted)
3071 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003072
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303073 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003074
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003075 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003076
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003077 if (out->config.rate)
3078 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3079 out->config.rate;
3080
3081 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3082
3083 request_out_focus(out, ns);
3084
3085 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003086 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003087 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303088 out->convert_buffer != NULL) {
3089
3090 memcpy_by_audio_format(out->convert_buffer,
3091 out->hal_op_format,
3092 buffer,
3093 out->hal_ip_format,
3094 out->config.period_size * out->config.channels);
3095
3096 ret = pcm_write(out->pcm, out->convert_buffer,
3097 (out->config.period_size *
3098 out->config.channels *
3099 format_to_bitwidth_table[out->hal_op_format]));
3100 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003101 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303102 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003103
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003104 release_out_focus(out);
3105
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303106 if (ret < 0)
3107 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303108 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3109 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3110 else
3111 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 }
3114
3115exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303116 /* ToDo: There may be a corner case when SSR happens back to back during
3117 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303118 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303119 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303120 }
3121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 pthread_mutex_unlock(&out->lock);
3123
3124 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003125 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003126 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303127 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303128 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303129 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303130 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303131 out->standby = true;
3132 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303134 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3135 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3136 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 }
3138 return bytes;
3139}
3140
3141static int out_get_render_position(const struct audio_stream_out *stream,
3142 uint32_t *dsp_frames)
3143{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303145 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003146
3147 if (dsp_frames == NULL)
3148 return -EINVAL;
3149
3150 *dsp_frames = 0;
3151 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003152 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303153
3154 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3155 * this operation and adev_close_output_stream(where out gets reset).
3156 */
3157 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3158 *dsp_frames = get_actual_pcm_frames_rendered(out);
3159 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3160 return 0;
3161 }
3162
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003163 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303164 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303165 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003166 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303167 if (ret < 0)
3168 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303170 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 }
3172 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303173 if (-ENETRESET == ret) {
3174 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3175 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3176 return -EINVAL;
3177 } else if(ret < 0) {
3178 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3179 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303180 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3181 /*
3182 * Handle corner case where compress session is closed during SSR
3183 * and timestamp is queried
3184 */
3185 ALOGE(" ERROR: sound card not active, return error");
3186 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303187 } else {
3188 return 0;
3189 }
Zhou Song32a556e2015-05-05 10:46:56 +08003190 } else if (audio_is_linear_pcm(out->format)) {
3191 *dsp_frames = out->written;
3192 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 } else
3194 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195}
3196
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003197static int out_add_audio_effect(const struct audio_stream *stream __unused,
3198 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199{
3200 return 0;
3201}
3202
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003203static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3204 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205{
3206 return 0;
3207}
3208
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003209static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3210 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211{
3212 return -EINVAL;
3213}
3214
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003215static int out_get_presentation_position(const struct audio_stream_out *stream,
3216 uint64_t *frames, struct timespec *timestamp)
3217{
3218 struct stream_out *out = (struct stream_out *)stream;
3219 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003220 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003221
Ashish Jain5106d362016-05-11 19:23:33 +05303222 /* below piece of code is not guarded against any lock because audioFliner serializes
3223 * this operation and adev_close_output_stream( where out gets reset).
3224 */
3225 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3226 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3227 *frames = get_actual_pcm_frames_rendered(out);
3228 /* this is the best we can do */
3229 clock_gettime(CLOCK_MONOTONIC, timestamp);
3230 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3231 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3232 return 0;
3233 }
3234
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003235 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003236
Ashish Jain5106d362016-05-11 19:23:33 +05303237 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3238 ret = compress_get_tstamp(out->compr, &dsp_frames,
3239 &out->sample_rate);
3240 ALOGVV("%s rendered frames %ld sample_rate %d",
3241 __func__, dsp_frames, out->sample_rate);
3242 *frames = dsp_frames;
3243 if (ret < 0)
3244 ret = -errno;
3245 if (-ENETRESET == ret) {
3246 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3247 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3248 ret = -EINVAL;
3249 } else
3250 ret = 0;
3251 /* this is the best we can do */
3252 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003253 } else {
3254 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003255 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003256 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3257 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003258 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003259 // This adjustment accounts for buffering after app processor.
3260 // It is based on estimated DSP latency per use case, rather than exact.
3261 signed_frames -=
3262 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3263
Eric Laurent949a0892013-09-20 09:20:13 -07003264 // It would be unusual for this value to be negative, but check just in case ...
3265 if (signed_frames >= 0) {
3266 *frames = signed_frames;
3267 ret = 0;
3268 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003269 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303270 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3271 *frames = out->written;
3272 clock_gettime(CLOCK_MONOTONIC, timestamp);
3273 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003274 }
3275 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003276 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003277 return ret;
3278}
3279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280static int out_set_callback(struct audio_stream_out *stream,
3281 stream_callback_t callback, void *cookie)
3282{
3283 struct stream_out *out = (struct stream_out *)stream;
3284
3285 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003286 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 out->offload_callback = callback;
3288 out->offload_cookie = cookie;
3289 pthread_mutex_unlock(&out->lock);
3290 return 0;
3291}
3292
3293static int out_pause(struct audio_stream_out* stream)
3294{
3295 struct stream_out *out = (struct stream_out *)stream;
3296 int status = -ENOSYS;
3297 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003298 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003299 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003300 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303302 struct audio_device *adev = out->dev;
3303 int snd_scard_state = get_snd_card_state(adev);
3304
3305 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3306 status = compress_pause(out->compr);
3307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003309
Mingming Yin21854652016-04-13 11:54:02 -07003310 if (audio_extn_passthru_is_active()) {
3311 ALOGV("offload use case, pause passthru");
3312 audio_extn_passthru_on_pause(out);
3313 }
3314
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303315 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003316 audio_extn_dts_notify_playback_state(out->usecase, 0,
3317 out->sample_rate, popcount(out->channel_mask),
3318 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003319 }
3320 pthread_mutex_unlock(&out->lock);
3321 }
3322 return status;
3323}
3324
3325static int out_resume(struct audio_stream_out* stream)
3326{
3327 struct stream_out *out = (struct stream_out *)stream;
3328 int status = -ENOSYS;
3329 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003330 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003331 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003333 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303335 struct audio_device *adev = out->dev;
3336 int snd_scard_state = get_snd_card_state(adev);
3337
Mingming Yin21854652016-04-13 11:54:02 -07003338 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3339 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3340 pthread_mutex_lock(&out->dev->lock);
3341 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003342 pthread_mutex_unlock(&out->dev->lock);
3343 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303344 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003345 }
3346 if (!status) {
3347 out->offload_state = OFFLOAD_STATE_PLAYING;
3348 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303349 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003350 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3351 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003352 }
3353 pthread_mutex_unlock(&out->lock);
3354 }
3355 return status;
3356}
3357
3358static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3359{
3360 struct stream_out *out = (struct stream_out *)stream;
3361 int status = -ENOSYS;
3362 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003363 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003364 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3366 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3367 else
3368 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3369 pthread_mutex_unlock(&out->lock);
3370 }
3371 return status;
3372}
3373
3374static int out_flush(struct audio_stream_out* stream)
3375{
3376 struct stream_out *out = (struct stream_out *)stream;
3377 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003378 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003379 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003380 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003381 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3382 stop_compressed_output_l(out);
3383 out->written = 0;
3384 } else {
3385 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3386 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003388 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389 return 0;
3390 }
3391 return -ENOSYS;
3392}
3393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394/** audio_stream_in implementation **/
3395static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3396{
3397 struct stream_in *in = (struct stream_in *)stream;
3398
3399 return in->config.rate;
3400}
3401
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003402static int in_set_sample_rate(struct audio_stream *stream __unused,
3403 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404{
3405 return -ENOSYS;
3406}
3407
3408static size_t in_get_buffer_size(const struct audio_stream *stream)
3409{
3410 struct stream_in *in = (struct stream_in *)stream;
3411
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003412 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3413 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003414 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3415 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303416 else if(audio_extn_cin_attached_usecase(in->usecase))
3417 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003418
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003419 return in->config.period_size * in->af_period_multiplier *
3420 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421}
3422
3423static uint32_t in_get_channels(const struct audio_stream *stream)
3424{
3425 struct stream_in *in = (struct stream_in *)stream;
3426
3427 return in->channel_mask;
3428}
3429
3430static audio_format_t in_get_format(const struct audio_stream *stream)
3431{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003432 struct stream_in *in = (struct stream_in *)stream;
3433
3434 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435}
3436
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003437static int in_set_format(struct audio_stream *stream __unused,
3438 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439{
3440 return -ENOSYS;
3441}
3442
3443static int in_standby(struct audio_stream *stream)
3444{
3445 struct stream_in *in = (struct stream_in *)stream;
3446 struct audio_device *adev = in->dev;
3447 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303448 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3449 stream, in->usecase, use_case_table[in->usecase]);
3450
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003451 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003452 if (!in->standby && in->is_st_session) {
3453 ALOGD("%s: sound trigger pcm stop lab", __func__);
3454 audio_extn_sound_trigger_stop_lab(in);
3455 in->standby = 1;
3456 }
3457
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003459 if (adev->adm_deregister_stream)
3460 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3461
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003462 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003464 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3465 voice_extn_compress_voip_close_input_stream(stream);
3466 ALOGD("VOIP input entered standby");
3467 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303468 if (audio_extn_cin_attached_usecase(in->usecase))
3469 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003470 if (in->pcm) {
3471 pcm_close(in->pcm);
3472 in->pcm = NULL;
3473 }
3474 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003475 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003476 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 }
3478 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003479 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480 return status;
3481}
3482
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003483static int in_dump(const struct audio_stream *stream __unused,
3484 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485{
3486 return 0;
3487}
3488
3489static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3490{
3491 struct stream_in *in = (struct stream_in *)stream;
3492 struct audio_device *adev = in->dev;
3493 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003495 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303497 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 parms = str_parms_create_str(kvpairs);
3499
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303500 if (!parms)
3501 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003502 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003503 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003504
3505 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3506 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 val = atoi(value);
3508 /* no audio source uses val == 0 */
3509 if ((in->source != val) && (val != 0)) {
3510 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003511 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3512 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3513 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003514 (in->config.rate == 8000 || in->config.rate == 16000 ||
3515 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003516 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003517 err = voice_extn_compress_voip_open_input_stream(in);
3518 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003519 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003520 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003521 }
3522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 }
3524 }
3525
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003526 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3527 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003529 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 in->device = val;
3531 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003532 if (!in->standby && !in->is_st_session) {
3533 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003534 if (adev->adm_on_routing_change)
3535 adev->adm_on_routing_change(adev->adm_data,
3536 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003537 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 }
3540 }
3541
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303542 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3543 if (err >= 0) {
3544 strlcpy(in->profile, value, sizeof(in->profile));
3545 ALOGV("updating stream profile with value '%s'", in->profile);
3546 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3547 &adev->streams_input_cfg_list,
3548 in->device, in->flags, in->format,
3549 in->sample_rate, in->bit_width,
3550 in->profile, &in->app_type_cfg);
3551 }
3552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003554 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555
3556 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303557error:
Eric Laurent994a6932013-07-17 11:51:42 -07003558 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 return ret;
3560}
3561
3562static char* in_get_parameters(const struct audio_stream *stream,
3563 const char *keys)
3564{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003565 struct stream_in *in = (struct stream_in *)stream;
3566 struct str_parms *query = str_parms_create_str(keys);
3567 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003568 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003569
3570 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003571 if (reply) {
3572 str_parms_destroy(reply);
3573 }
3574 if (query) {
3575 str_parms_destroy(query);
3576 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003577 ALOGE("in_get_parameters: failed to create query or reply");
3578 return NULL;
3579 }
3580
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003581 ALOGV("%s: enter: keys - %s", __func__, keys);
3582
3583 voice_extn_in_get_parameters(in, query, reply);
3584
3585 str = str_parms_to_str(reply);
3586 str_parms_destroy(query);
3587 str_parms_destroy(reply);
3588
3589 ALOGV("%s: exit: returns - %s", __func__, str);
3590 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591}
3592
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003593static int in_set_gain(struct audio_stream_in *stream __unused,
3594 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595{
3596 return 0;
3597}
3598
3599static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3600 size_t bytes)
3601{
3602 struct stream_in *in = (struct stream_in *)stream;
3603 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303604 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303605 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303606 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003608 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303609
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003610 if (in->is_st_session) {
3611 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3612 /* Read from sound trigger HAL */
3613 audio_extn_sound_trigger_read(in, buffer, bytes);
3614 pthread_mutex_unlock(&in->lock);
3615 return bytes;
3616 }
3617
Ashish Jainbbce4322016-02-16 13:25:27 +05303618 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003619 ALOGD(" %s: sound card is not active/SSR state", __func__);
3620 ret= -EIO;;
3621 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303622 }
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003625 pthread_mutex_lock(&adev->lock);
3626 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3627 ret = voice_extn_compress_voip_start_input_stream(in);
3628 else
3629 ret = start_input_stream(in);
3630 pthread_mutex_unlock(&adev->lock);
3631 if (ret != 0) {
3632 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 }
3634 in->standby = 0;
3635 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003637 // what's the duration requested by the client?
3638 long ns = 0;
3639
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303640 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003641 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3642 in->config.rate;
3643
3644 request_in_focus(in, ns);
3645 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003646
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303647 if (audio_extn_cin_attached_usecase(in->usecase)) {
3648 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3649 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303650 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003651 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303652 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003653 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003654 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003655 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303656 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003657 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303658 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3659 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3660 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3661 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303662 ret = -EINVAL;
3663 goto exit;
3664 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303665 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303666 ret = -errno;
3667 }
3668 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303669 /* bytes read is always set to bytes for non compress usecases */
3670 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 }
3672
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003673 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 /*
3676 * Instead of writing zeroes here, we could trust the hardware
3677 * to always provide zeroes when muted.
3678 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303679 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3680 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 memset(buffer, 0, bytes);
3682
3683exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303684 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303685 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003686 if (-ENETRESET == ret)
3687 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 pthread_mutex_unlock(&in->lock);
3690
3691 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303692 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303693 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303694 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303695 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303696 in->standby = true;
3697 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303698 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003700 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303701 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303702 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303704 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705}
3706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003707static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708{
3709 return 0;
3710}
3711
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003712static int add_remove_audio_effect(const struct audio_stream *stream,
3713 effect_handle_t effect,
3714 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003716 struct stream_in *in = (struct stream_in *)stream;
3717 int status = 0;
3718 effect_descriptor_t desc;
3719
3720 status = (*effect)->get_descriptor(effect, &desc);
3721 if (status != 0)
3722 return status;
3723
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003724 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003725 pthread_mutex_lock(&in->dev->lock);
3726 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3727 in->enable_aec != enable &&
3728 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3729 in->enable_aec = enable;
3730 if (!in->standby)
3731 select_devices(in->dev, in->usecase);
3732 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003733 if (in->enable_ns != enable &&
3734 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3735 in->enable_ns = enable;
3736 if (!in->standby)
3737 select_devices(in->dev, in->usecase);
3738 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003739 pthread_mutex_unlock(&in->dev->lock);
3740 pthread_mutex_unlock(&in->lock);
3741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 return 0;
3743}
3744
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003745static int in_add_audio_effect(const struct audio_stream *stream,
3746 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747{
Eric Laurent994a6932013-07-17 11:51:42 -07003748 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003749 return add_remove_audio_effect(stream, effect, true);
3750}
3751
3752static int in_remove_audio_effect(const struct audio_stream *stream,
3753 effect_handle_t effect)
3754{
Eric Laurent994a6932013-07-17 11:51:42 -07003755 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003756 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757}
3758
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303759int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 audio_io_handle_t handle,
3761 audio_devices_t devices,
3762 audio_output_flags_t flags,
3763 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003764 struct audio_stream_out **stream_out,
3765 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766{
3767 struct audio_device *adev = (struct audio_device *)dev;
3768 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303769 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003770 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303773
3774 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3775 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003776 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303777 return -EINVAL;
3778 }
3779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3781
Mingming Yin3a941d42016-02-17 18:08:05 -08003782 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3783 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303784 devices, flags, &out->stream);
3785
3786
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003787 if (!out) {
3788 return -ENOMEM;
3789 }
3790
Haynes Mathew George204045b2015-02-25 20:32:03 -08003791 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003792 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003793 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795 if (devices == AUDIO_DEVICE_NONE)
3796 devices = AUDIO_DEVICE_OUT_SPEAKER;
3797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 out->flags = flags;
3799 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003800 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003801 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802 out->sample_rate = config->sample_rate;
3803 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3804 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003805 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003806 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003807 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303808 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809
Mingming Yin3a941d42016-02-17 18:08:05 -08003810 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3811 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3812 pthread_mutex_lock(&adev->lock);
3813 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3814 ret = read_hdmi_sink_caps(out);
3815 pthread_mutex_unlock(&adev->lock);
3816 if (ret != 0) {
3817 if (ret == -ENOSYS) {
3818 /* ignore and go with default */
3819 ret = 0;
3820 } else {
3821 ALOGE("error reading hdmi sink caps");
3822 goto error_open;
3823 }
3824 }
3825 }
3826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003828 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303829 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3830 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003831 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3832 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3833
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003834 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003835 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3836 /*
3837 * Do not handle stereo output in Multi-channel cases
3838 * Stereo case is handled in normal playback path
3839 */
3840 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3841 ret = AUDIO_CHANNEL_OUT_STEREO;
3842 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003843
3844 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3845 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003846 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003847 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003848 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003849
3850 if (config->sample_rate == 0)
3851 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3852 if (config->channel_mask == 0)
3853 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003854 if (config->format == 0)
3855 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003856
3857 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003859 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3861 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003863 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003865 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3866 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003867 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003868 ret = voice_extn_compress_voip_open_output_stream(out);
3869 if (ret != 0) {
3870 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3871 __func__, ret);
3872 goto error_open;
3873 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003874 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3875 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3876
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003877 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3878 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3879 ALOGE("%s: Unsupported Offload information", __func__);
3880 ret = -EINVAL;
3881 goto error_open;
3882 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003883
Mingming Yin3a941d42016-02-17 18:08:05 -08003884 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003885 if(config->offload_info.format == 0)
3886 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003887 if (config->offload_info.sample_rate == 0)
3888 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003889 }
3890
Mingming Yin90310102013-11-13 16:57:00 -08003891 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303892 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003893 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003894 ret = -EINVAL;
3895 goto error_open;
3896 }
3897
3898 out->compr_config.codec = (struct snd_codec *)
3899 calloc(1, sizeof(struct snd_codec));
3900
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003901 if (!out->compr_config.codec) {
3902 ret = -ENOMEM;
3903 goto error_open;
3904 }
3905
vivek mehta0ea887a2015-08-26 14:01:20 -07003906 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303907 out->stream.pause = out_pause;
3908 out->stream.flush = out_flush;
3909 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003910 out->usecase = get_offload_usecase(adev, true);
3911 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003912 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003913 out->stream.set_callback = out_set_callback;
3914 out->stream.pause = out_pause;
3915 out->stream.resume = out_resume;
3916 out->stream.drain = out_drain;
3917 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003918 out->usecase = get_offload_usecase(adev, false);
3919 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003920 }
vivek mehta446c3962015-09-14 10:57:35 -07003921
3922 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003923 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3924 config->format == 0 && config->sample_rate == 0 &&
3925 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003926 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003927 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3928 } else {
3929 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3930 ret = -EEXIST;
3931 goto error_open;
3932 }
vivek mehta446c3962015-09-14 10:57:35 -07003933 }
3934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003935 if (config->offload_info.channel_mask)
3936 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003937 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003938 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003939 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003940 } else {
3941 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3942 ret = -EINVAL;
3943 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003944 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003945
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003946 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003947 out->sample_rate = config->offload_info.sample_rate;
3948
Mingming Yin3ee55c62014-08-04 14:23:35 -07003949 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003950
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303951 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3952 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3953 audio_extn_dolby_send_ddp_endp_params(adev);
3954 audio_extn_dolby_set_dmid(adev);
3955 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003956
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003957 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003958 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959 out->compr_config.codec->bit_rate =
3960 config->offload_info.bit_rate;
3961 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303962 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003963 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303964 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003965 /*TODO: Do we need to change it for passthrough */
3966 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003967
Manish Dewangana6fc5442015-08-24 20:30:31 +05303968 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3969 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3970 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3971 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303972
3973 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3974 AUDIO_FORMAT_PCM) {
3975
3976 /*Based on platform support, configure appropriate alsa format for corresponding
3977 *hal input format.
3978 */
3979 out->compr_config.codec->format = hal_format_to_alsa(
3980 config->offload_info.format);
3981
Ashish Jain83a6cc22016-06-28 14:34:17 +05303982 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303983 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303984 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303985
3986 /*for direct PCM playback populate bit_width based on selected alsa format as
3987 *hal input format and alsa format might differ based on platform support.
3988 */
3989 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303990 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303991
3992 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3993
3994 /* Check if alsa session is configured with the same format as HAL input format,
3995 * if not then derive correct fragment size needed to accomodate the
3996 * conversion of HAL input format to alsa format.
3997 */
3998 audio_extn_utils_update_direct_pcm_fragment_size(out);
3999
4000 /*if hal input and output fragment size is different this indicates HAL input format is
4001 *not same as the alsa format
4002 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304003 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304004 /*Allocate a buffer to convert input data to the alsa configured format.
4005 *size of convert buffer is equal to the size required to hold one fragment size
4006 *worth of pcm data, this is because flinger does not write more than fragment_size
4007 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304008 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4009 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304010 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4011 ret = -ENOMEM;
4012 goto error_open;
4013 }
4014 }
4015 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4016 out->compr_config.fragment_size =
4017 audio_extn_passthru_get_buffer_size(&config->offload_info);
4018 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4019 } else {
4020 out->compr_config.fragment_size =
4021 platform_get_compress_offload_buffer_size(&config->offload_info);
4022 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4023 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004024
Amit Shekhar6f461b12014-08-01 14:52:58 -07004025 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304026 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004027
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004028 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4029 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004030
Alexy Josephaa54c872014-12-03 02:46:47 -08004031
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004032 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304033 out->send_next_track_params = false;
4034 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004035 out->offload_state = OFFLOAD_STATE_IDLE;
4036 out->playback_started = 0;
4037
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004038 audio_extn_dts_create_state_notifier_node(out->usecase);
4039
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004040 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4041 __func__, config->offload_info.version,
4042 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304043
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304044 /* Check if DSD audio format is supported in codec
4045 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304046 */
4047
4048 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304049 (!platform_check_codec_dsd_support(adev->platform) ||
4050 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304051 ret = -EINVAL;
4052 goto error_open;
4053 }
4054
Ashish Jain5106d362016-05-11 19:23:33 +05304055 /* Disable gapless if any of the following is true
4056 * passthrough playback
4057 * AV playback
4058 * Direct PCM playback
4059 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304060 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304061 (config->format == AUDIO_FORMAT_DSD) ||
4062 config->offload_info.has_video ||
4063 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304064 check_and_set_gapless_mode(adev, false);
4065 } else
4066 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004067
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304068 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004069 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4070 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304071 if (config->format == AUDIO_FORMAT_DSD) {
4072 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4073 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4074 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004075
4076 create_offload_callback_thread(out);
4077
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004078 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304079 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004080 if (ret != 0) {
4081 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4082 __func__, ret);
4083 goto error_open;
4084 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004085 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4086 if (config->sample_rate == 0)
4087 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4088 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4089 config->sample_rate != 8000) {
4090 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4091 ret = -EINVAL;
4092 goto error_open;
4093 }
4094 out->sample_rate = config->sample_rate;
4095 out->config.rate = config->sample_rate;
4096 if (config->format == AUDIO_FORMAT_DEFAULT)
4097 config->format = AUDIO_FORMAT_PCM_16_BIT;
4098 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4099 config->format = AUDIO_FORMAT_PCM_16_BIT;
4100 ret = -EINVAL;
4101 goto error_open;
4102 }
4103 out->format = config->format;
4104 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4105 out->config = pcm_config_afe_proxy_playback;
4106 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004107 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304108 unsigned int channels = 0;
4109 /*Update config params to default if not set by the caller*/
4110 if (config->sample_rate == 0)
4111 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4112 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4113 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4114 if (config->format == AUDIO_FORMAT_DEFAULT)
4115 config->format = AUDIO_FORMAT_PCM_16_BIT;
4116
4117 channels = audio_channel_count_from_out_mask(out->channel_mask);
4118
Ashish Jain83a6cc22016-06-28 14:34:17 +05304119 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4120 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004121 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4122 out->flags);
4123 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304124 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4125 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4126 out->config = pcm_config_low_latency;
4127 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4128 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4129 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304130 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4131 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4132 if (out->config.period_size <= 0) {
4133 ALOGE("Invalid configuration period size is not valid");
4134 ret = -EINVAL;
4135 goto error_open;
4136 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304137 } else {
4138 /* primary path is the default path selected if no other outputs are available/suitable */
4139 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4140 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4141 }
4142 out->hal_ip_format = format = out->format;
4143 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4144 out->hal_op_format = pcm_format_to_hal(out->config.format);
4145 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4146 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004147 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304148 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304149 if (out->hal_ip_format != out->hal_op_format) {
4150 uint32_t buffer_size = out->config.period_size *
4151 format_to_bitwidth_table[out->hal_op_format] *
4152 out->config.channels;
4153 out->convert_buffer = calloc(1, buffer_size);
4154 if (out->convert_buffer == NULL){
4155 ALOGE("Allocation failed for convert buffer for size %d",
4156 out->compr_config.fragment_size);
4157 ret = -ENOMEM;
4158 goto error_open;
4159 }
4160 ALOGD("Convert buffer allocated of size %d", buffer_size);
4161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 }
4163
Ashish Jain83a6cc22016-06-28 14:34:17 +05304164 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4165 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4166
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004167 /* TODO remove this hardcoding and check why width is zero*/
4168 if (out->bit_width == 0)
4169 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304170 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004171 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004172 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304173 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304174 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004175 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4176 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4177 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004178 if(adev->primary_output == NULL)
4179 adev->primary_output = out;
4180 else {
4181 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004182 ret = -EEXIST;
4183 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004184 }
4185 }
4186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 /* Check if this usecase is already existing */
4188 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004189 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4190 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004193 ret = -EEXIST;
4194 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 }
4196 pthread_mutex_unlock(&adev->lock);
4197
4198 out->stream.common.get_sample_rate = out_get_sample_rate;
4199 out->stream.common.set_sample_rate = out_set_sample_rate;
4200 out->stream.common.get_buffer_size = out_get_buffer_size;
4201 out->stream.common.get_channels = out_get_channels;
4202 out->stream.common.get_format = out_get_format;
4203 out->stream.common.set_format = out_set_format;
4204 out->stream.common.standby = out_standby;
4205 out->stream.common.dump = out_dump;
4206 out->stream.common.set_parameters = out_set_parameters;
4207 out->stream.common.get_parameters = out_get_parameters;
4208 out->stream.common.add_audio_effect = out_add_audio_effect;
4209 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4210 out->stream.get_latency = out_get_latency;
4211 out->stream.set_volume = out_set_volume;
4212 out->stream.write = out_write;
4213 out->stream.get_render_position = out_get_render_position;
4214 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004215 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004217 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004219 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004220 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221
4222 config->format = out->stream.common.get_format(&out->stream.common);
4223 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4224 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4225
4226 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304227 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004228 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004229
4230 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4231 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4232 popcount(out->channel_mask), out->playback_started);
4233
Eric Laurent994a6932013-07-17 11:51:42 -07004234 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004236
4237error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304238 if (out->convert_buffer)
4239 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004240 free(out);
4241 *stream_out = NULL;
4242 ALOGD("%s: exit: ret %d", __func__, ret);
4243 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244}
4245
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304246void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 struct audio_stream_out *stream)
4248{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004249 struct stream_out *out = (struct stream_out *)stream;
4250 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004251 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004252
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304253 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4254
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004255 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304256 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004257 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304258 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004259 if(ret != 0)
4260 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4261 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004262 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004263 out_standby(&stream->common);
4264
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004265 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004266 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004267 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004268 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004269 if (out->compr_config.codec != NULL)
4270 free(out->compr_config.codec);
4271 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004272
Ashish Jain83a6cc22016-06-28 14:34:17 +05304273 if (out->convert_buffer != NULL) {
4274 free(out->convert_buffer);
4275 out->convert_buffer = NULL;
4276 }
4277
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004278 if (adev->voice_tx_output == out)
4279 adev->voice_tx_output = NULL;
4280
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004281 pthread_cond_destroy(&out->cond);
4282 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004284 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285}
4286
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004287static void close_compress_sessions(struct audio_device *adev)
4288{
Mingming Yin7b762e72015-03-04 13:47:32 -08004289 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304290 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004291 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004292 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304293
4294 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004295 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304296 if (is_offload_usecase(usecase->id)) {
4297 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004298 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4299 out = usecase->stream.out;
4300 pthread_mutex_unlock(&adev->lock);
4301 out_standby(&out->stream.common);
4302 pthread_mutex_lock(&adev->lock);
4303 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304304 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004305 }
4306 pthread_mutex_unlock(&adev->lock);
4307}
4308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4310{
4311 struct audio_device *adev = (struct audio_device *)dev;
4312 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004314 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004315 int ret;
4316 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004318 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304321 if (!parms)
4322 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004323 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4324 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304325 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304326 if (strstr(snd_card_status, "OFFLINE")) {
4327 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304328 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004329 //close compress sessions on OFFLINE status
4330 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304331 } else if (strstr(snd_card_status, "ONLINE")) {
4332 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304333 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004334 //send dts hpx license if enabled
4335 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304336 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304337 }
4338
4339 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004340 status = voice_set_parameters(adev, parms);
4341 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004342 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004344 status = platform_set_parameters(adev->platform, parms);
4345 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004346 goto done;
4347
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004348 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4349 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004350 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4352 adev->bluetooth_nrec = true;
4353 else
4354 adev->bluetooth_nrec = false;
4355 }
4356
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004357 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4358 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4360 adev->screen_off = false;
4361 else
4362 adev->screen_off = true;
4363 }
4364
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004365 ret = str_parms_get_int(parms, "rotation", &val);
4366 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004367 bool reverse_speakers = false;
4368 switch(val) {
4369 // FIXME: note that the code below assumes that the speakers are in the correct placement
4370 // relative to the user when the device is rotated 90deg from its default rotation. This
4371 // assumption is device-specific, not platform-specific like this code.
4372 case 270:
4373 reverse_speakers = true;
4374 break;
4375 case 0:
4376 case 90:
4377 case 180:
4378 break;
4379 default:
4380 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004381 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004382 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004383 if (status == 0) {
4384 if (adev->speaker_lr_swap != reverse_speakers) {
4385 adev->speaker_lr_swap = reverse_speakers;
4386 // only update the selected device if there is active pcm playback
4387 struct audio_usecase *usecase;
4388 struct listnode *node;
4389 list_for_each(node, &adev->usecase_list) {
4390 usecase = node_to_item(node, struct audio_usecase, list);
4391 if (usecase->type == PCM_PLAYBACK) {
4392 select_devices(adev, usecase->id);
4393 break;
4394 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004395 }
4396 }
4397 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004398 }
4399
Mingming Yin514a8bc2014-07-29 15:22:21 -07004400 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4401 if (ret >= 0) {
4402 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4403 adev->bt_wb_speech_enabled = true;
4404 else
4405 adev->bt_wb_speech_enabled = false;
4406 }
4407
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004408 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4409 if (ret >= 0) {
4410 val = atoi(value);
4411 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004412 ALOGV("cache new ext disp type and edid");
4413 ret = platform_get_ext_disp_type(adev->platform);
4414 if (ret < 0) {
4415 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004416 status = ret;
4417 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004418 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004419 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004420 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004421 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004422 /*
4423 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4424 * Per AudioPolicyManager, USB device is higher priority than WFD.
4425 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4426 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4427 * starting voice call on USB
4428 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004429 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4430 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004431 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4432 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004433 }
vivek mehta344576a2016-04-12 18:56:03 -07004434 ALOGV("detected USB connect .. disable proxy");
4435 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004436 }
4437 }
4438
4439 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4440 if (ret >= 0) {
4441 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004442 /*
4443 * The HDMI / Displayport disconnect handling has been moved to
4444 * audio extension to ensure that its parameters are not
4445 * invalidated prior to updating sysfs of the disconnect event
4446 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4447 */
4448 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004449 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004450 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4451 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304452 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4453 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004454 }
vivek mehta344576a2016-04-12 18:56:03 -07004455 ALOGV("detected USB disconnect .. enable proxy");
4456 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004457 }
4458 }
4459
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304460 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4461 if (ret >= 0) {
4462 struct audio_usecase *usecase;
4463 struct listnode *node;
4464 list_for_each(node, &adev->usecase_list) {
4465 usecase = node_to_item(node, struct audio_usecase, list);
4466 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004467 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304468 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304469 lock_output_stream(usecase->stream.out);
4470 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304471 //force device switch to re configure encoder
4472 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304473 audio_extn_a2dp_set_handoff_mode(false);
4474 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304475 break;
4476 }
4477 }
4478 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304479 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004480done:
4481 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004482 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304483error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004484 ALOGV("%s: exit with code(%d)", __func__, status);
4485 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004486}
4487
4488static char* adev_get_parameters(const struct audio_hw_device *dev,
4489 const char *keys)
4490{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004491 struct audio_device *adev = (struct audio_device *)dev;
4492 struct str_parms *reply = str_parms_create();
4493 struct str_parms *query = str_parms_create_str(keys);
4494 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304495 char value[256] = {0};
4496 int ret = 0;
4497
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004498 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004499 if (reply) {
4500 str_parms_destroy(reply);
4501 }
4502 if (query) {
4503 str_parms_destroy(query);
4504 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004505 ALOGE("adev_get_parameters: failed to create query or reply");
4506 return NULL;
4507 }
4508
Naresh Tannirud7205b62014-06-20 02:54:48 +05304509 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4510 sizeof(value));
4511 if (ret >=0) {
4512 int val = 1;
4513 pthread_mutex_lock(&adev->snd_card_status.lock);
4514 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4515 val = 0;
4516 pthread_mutex_unlock(&adev->snd_card_status.lock);
4517 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4518 goto exit;
4519 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004520
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004521 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004522 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004523 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004524 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304525 pthread_mutex_unlock(&adev->lock);
4526
Naresh Tannirud7205b62014-06-20 02:54:48 +05304527exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004528 str = str_parms_to_str(reply);
4529 str_parms_destroy(query);
4530 str_parms_destroy(reply);
4531
4532 ALOGV("%s: exit: returns - %s", __func__, str);
4533 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004534}
4535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004536static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004537{
4538 return 0;
4539}
4540
4541static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4542{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004543 int ret;
4544 struct audio_device *adev = (struct audio_device *)dev;
4545 pthread_mutex_lock(&adev->lock);
4546 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004547 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004548 pthread_mutex_unlock(&adev->lock);
4549 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550}
4551
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004552static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4553 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554{
4555 return -ENOSYS;
4556}
4557
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004558static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4559 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560{
4561 return -ENOSYS;
4562}
4563
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004564static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4565 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566{
4567 return -ENOSYS;
4568}
4569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004570static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4571 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572{
4573 return -ENOSYS;
4574}
4575
4576static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4577{
4578 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580 pthread_mutex_lock(&adev->lock);
4581 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004582 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004584 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004585 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004586 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004587 adev->current_call_output = NULL;
4588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 }
4590 pthread_mutex_unlock(&adev->lock);
4591 return 0;
4592}
4593
4594static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4595{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004596 int ret;
4597
4598 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004599 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004600 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4601 pthread_mutex_unlock(&adev->lock);
4602
4603 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604}
4605
4606static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4607{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004608 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609 return 0;
4610}
4611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004612static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 const struct audio_config *config)
4614{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004615 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004617 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4618 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004619}
4620
4621static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004622 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623 audio_devices_t devices,
4624 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004625 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304626 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004627 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004628 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004629{
4630 struct audio_device *adev = (struct audio_device *)dev;
4631 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004632 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004633 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004634 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304635 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304638 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4639 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642
4643 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004644
4645 if (!in) {
4646 ALOGE("failed to allocate input stream");
4647 return -ENOMEM;
4648 }
4649
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304650 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304651 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4652 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004653 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004654 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 in->stream.common.get_sample_rate = in_get_sample_rate;
4657 in->stream.common.set_sample_rate = in_set_sample_rate;
4658 in->stream.common.get_buffer_size = in_get_buffer_size;
4659 in->stream.common.get_channels = in_get_channels;
4660 in->stream.common.get_format = in_get_format;
4661 in->stream.common.set_format = in_set_format;
4662 in->stream.common.standby = in_standby;
4663 in->stream.common.dump = in_dump;
4664 in->stream.common.set_parameters = in_set_parameters;
4665 in->stream.common.get_parameters = in_get_parameters;
4666 in->stream.common.add_audio_effect = in_add_audio_effect;
4667 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4668 in->stream.set_gain = in_set_gain;
4669 in->stream.read = in_read;
4670 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4671
4672 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004673 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675 in->standby = 1;
4676 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004677 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004678 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004680 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004681 if (in->realtime) {
4682 in->config = pcm_config_audio_capture_rt;
4683 in->sample_rate = in->config.rate;
4684 in->af_period_multiplier = af_period_multiplier;
4685 } else {
4686 in->config = pcm_config_audio_capture;
4687 in->config.rate = config->sample_rate;
4688 in->sample_rate = config->sample_rate;
4689 in->af_period_multiplier = 1;
4690 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304691 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304693 /* restrict 24 bit capture for unprocessed source only
4694 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4695 */
4696 if (config->format == AUDIO_FORMAT_DEFAULT) {
4697 config->format = AUDIO_FORMAT_PCM_16_BIT;
4698 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4699 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4700 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4701 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4702 bool ret_error = false;
4703 in->bit_width = 24;
4704 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4705 from HAL is 24_packed and 8_24
4706 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4707 24_packed return error indicating supported format is 24_packed
4708 *> In case of any other source requesting 24 bit or float return error
4709 indicating format supported is 16 bit only.
4710
4711 on error flinger will retry with supported format passed
4712 */
4713 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4714 (source != AUDIO_SOURCE_CAMCORDER)) {
4715 config->format = AUDIO_FORMAT_PCM_16_BIT;
4716 if (config->sample_rate > 48000)
4717 config->sample_rate = 48000;
4718 ret_error = true;
4719 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4720 in->config.format = PCM_FORMAT_S24_3LE;
4721 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4722 in->config.format = PCM_FORMAT_S24_LE;
4723 } else {
4724 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4725 ret_error = true;
4726 }
4727
4728 if (ret_error) {
4729 ret = -EINVAL;
4730 goto err_open;
4731 }
4732 }
4733
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304734 in->usecase = USECASE_AUDIO_RECORD;
4735 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4736 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4737 is_low_latency = true;
4738#if LOW_LATENCY_CAPTURE_USE_CASE
4739 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4740#endif
4741 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4742 }
4743
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304744 pthread_mutex_lock(&adev->lock);
4745 if (in->usecase == USECASE_AUDIO_RECORD) {
4746 if (!(adev->pcm_record_uc_state) &&
4747 ((flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0)) {
4748 ALOGV("%s: pcm record usecase", __func__);
4749 adev->pcm_record_uc_state = 1;
4750 } else {
4751 /*
4752 * Assign default compress record use case, actual use case
4753 * assignment will happen later.
4754 */
4755 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
4756 ALOGV("%s: compress record usecase", __func__);
4757 }
4758 }
4759 pthread_mutex_unlock(&adev->lock);
4760
4761 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304762 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4763 (adev->mode != AUDIO_MODE_IN_CALL)) {
4764 ret = -EINVAL;
4765 goto err_open;
4766 }
4767
4768 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4769 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004770 if (config->sample_rate == 0)
4771 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4772 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4773 config->sample_rate != 8000) {
4774 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4775 ret = -EINVAL;
4776 goto err_open;
4777 }
4778 if (config->format == AUDIO_FORMAT_DEFAULT)
4779 config->format = AUDIO_FORMAT_PCM_16_BIT;
4780 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4781 config->format = AUDIO_FORMAT_PCM_16_BIT;
4782 ret = -EINVAL;
4783 goto err_open;
4784 }
4785
4786 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4787 in->config = pcm_config_afe_proxy_record;
4788 in->config.channels = channel_count;
4789 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304790 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304791 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4792 in, config, &channel_mask_updated)) {
4793 if (channel_mask_updated == true) {
4794 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4795 __func__, config->channel_mask);
4796 ret = -EINVAL;
4797 goto err_open;
4798 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304799 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004800 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004801 audio_extn_compr_cap_format_supported(config->format) &&
4802 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004803 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304804 } else if (audio_extn_cin_applicable_stream(in)) {
4805 ret = audio_extn_cin_configure_input_stream(in);
4806 if (ret)
4807 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004808 } else {
4809 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004810 if (!in->realtime) {
4811 in->format = config->format;
4812 frame_size = audio_stream_in_frame_size(&in->stream);
4813 buffer_size = get_input_buffer_size(config->sample_rate,
4814 config->format,
4815 channel_count,
4816 is_low_latency);
4817 in->config.period_size = buffer_size / frame_size;
4818 }
4819
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004820 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4821 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4822 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004823 (in->config.rate == 8000 || in->config.rate == 16000 ||
4824 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004825 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4826 voice_extn_compress_voip_open_input_stream(in);
4827 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004828 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304830 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4831 &adev->streams_input_cfg_list,
4832 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304833 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304834
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004835 /* This stream could be for sound trigger lab,
4836 get sound trigger pcm if present */
4837 audio_extn_sound_trigger_check_and_get_session(in);
4838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004839 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004840 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004841 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842
4843err_open:
4844 free(in);
4845 *stream_in = NULL;
4846 return ret;
4847}
4848
4849static void adev_close_input_stream(struct audio_hw_device *dev,
4850 struct audio_stream_in *stream)
4851{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004852 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004853 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004854 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304855
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304856 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004857
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304858 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004859 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304860
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004861 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304862 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004863 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304864 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004865 if (ret != 0)
4866 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4867 __func__, ret);
4868 } else
4869 in_standby(&stream->common);
4870
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004871 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004872 audio_extn_ssr_deinit();
4873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304875 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004876 audio_extn_compr_cap_format_supported(in->config.format))
4877 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304878
4879 if (in->usecase == USECASE_AUDIO_RECORD) {
4880 pthread_mutex_lock(&adev->lock);
4881 adev->pcm_record_uc_state = 0;
4882 pthread_mutex_unlock(&adev->lock);
4883 }
4884
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304885 if (audio_extn_cin_attached_usecase(in->usecase))
4886 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004887
Mingming Yinfd7607b2016-01-22 12:48:44 -08004888 if (in->is_st_session) {
4889 ALOGV("%s: sound trigger pcm stop lab", __func__);
4890 audio_extn_sound_trigger_stop_lab(in);
4891 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004892 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 return;
4894}
4895
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004896static int adev_dump(const audio_hw_device_t *device __unused,
4897 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898{
4899 return 0;
4900}
4901
4902static int adev_close(hw_device_t *device)
4903{
4904 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004905
4906 if (!adev)
4907 return 0;
4908
4909 pthread_mutex_lock(&adev_init_lock);
4910
4911 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004912 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004913 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304914 audio_extn_utils_release_streams_cfg_lists(
4915 &adev->streams_output_cfg_list,
4916 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304917 if (audio_extn_qaf_is_enabled())
4918 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004919 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004920 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004921 free(adev->snd_dev_ref_cnt);
4922 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004923 if (adev->adm_deinit)
4924 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304925 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004926 free(device);
4927 adev = NULL;
4928 }
4929 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 return 0;
4932}
4933
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004934/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4935 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4936 * just that it _might_ work.
4937 */
4938static int period_size_is_plausible_for_low_latency(int period_size)
4939{
4940 switch (period_size) {
4941 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004942 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004943 case 240:
4944 case 320:
4945 case 480:
4946 return 1;
4947 default:
4948 return 0;
4949 }
4950}
4951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004952static int adev_open(const hw_module_t *module, const char *name,
4953 hw_device_t **device)
4954{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304955 int ret;
4956
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004957 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004958 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4959
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004960 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004961 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004962 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004963 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004964 ALOGD("%s: returning existing instance of adev", __func__);
4965 ALOGD("%s: exit", __func__);
4966 pthread_mutex_unlock(&adev_init_lock);
4967 return 0;
4968 }
4969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970 adev = calloc(1, sizeof(struct audio_device));
4971
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004972 if (!adev) {
4973 pthread_mutex_unlock(&adev_init_lock);
4974 return -ENOMEM;
4975 }
4976
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004977 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4980 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4981 adev->device.common.module = (struct hw_module_t *)module;
4982 adev->device.common.close = adev_close;
4983
4984 adev->device.init_check = adev_init_check;
4985 adev->device.set_voice_volume = adev_set_voice_volume;
4986 adev->device.set_master_volume = adev_set_master_volume;
4987 adev->device.get_master_volume = adev_get_master_volume;
4988 adev->device.set_master_mute = adev_set_master_mute;
4989 adev->device.get_master_mute = adev_get_master_mute;
4990 adev->device.set_mode = adev_set_mode;
4991 adev->device.set_mic_mute = adev_set_mic_mute;
4992 adev->device.get_mic_mute = adev_get_mic_mute;
4993 adev->device.set_parameters = adev_set_parameters;
4994 adev->device.get_parameters = adev_get_parameters;
4995 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4996 adev->device.open_output_stream = adev_open_output_stream;
4997 adev->device.close_output_stream = adev_close_output_stream;
4998 adev->device.open_input_stream = adev_open_input_stream;
4999 adev->device.close_input_stream = adev_close_input_stream;
5000 adev->device.dump = adev_dump;
5001
5002 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005004 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005005 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005008 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005009 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005010 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005011 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005012 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005013 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005014 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005015 adev->offload_usecases_state = 0;
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305016 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305017 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305018 adev->perf_lock_opts[0] = 0x101;
5019 adev->perf_lock_opts[1] = 0x20E;
5020 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305021
5022 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5023 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005025 adev->platform = platform_init(adev);
5026 if (!adev->platform) {
5027 free(adev->snd_dev_ref_cnt);
5028 free(adev);
5029 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5030 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005031 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305032 pthread_mutex_destroy(&adev->lock);
5033 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005034 return -EINVAL;
5035 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005036
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305037 if (audio_extn_qaf_is_enabled()) {
5038 ret = audio_extn_qaf_init(adev);
5039 if (ret < 0) {
5040 free(adev);
5041 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5042 *device = NULL;
5043 pthread_mutex_unlock(&adev_init_lock);
5044 pthread_mutex_destroy(&adev->lock);
5045 return ret;
5046 }
5047
5048 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5049 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5050 }
5051
Naresh Tanniru4c630392014-05-12 01:05:52 +05305052 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5053
Eric Laurentc4aef752013-09-12 17:45:53 -07005054 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5055 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5056 if (adev->visualizer_lib == NULL) {
5057 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5058 } else {
5059 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5060 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005061 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005062 "visualizer_hal_start_output");
5063 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005064 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005065 "visualizer_hal_stop_output");
5066 }
5067 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305068 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005069 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005070 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005071 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005072
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005073 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5074 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5075 if (adev->offload_effects_lib == NULL) {
5076 ALOGE("%s: DLOPEN failed for %s", __func__,
5077 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5078 } else {
5079 ALOGV("%s: DLOPEN successful for %s", __func__,
5080 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5081 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305082 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005083 "offload_effects_bundle_hal_start_output");
5084 adev->offload_effects_stop_output =
5085 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5086 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005087 adev->offload_effects_set_hpx_state =
5088 (int (*)(bool))dlsym(adev->offload_effects_lib,
5089 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305090 adev->offload_effects_get_parameters =
5091 (void (*)(struct str_parms *, struct str_parms *))
5092 dlsym(adev->offload_effects_lib,
5093 "offload_effects_bundle_get_parameters");
5094 adev->offload_effects_set_parameters =
5095 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5096 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005097 }
5098 }
5099
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005100 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5101 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5102 if (adev->adm_lib == NULL) {
5103 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5104 } else {
5105 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5106 adev->adm_init = (adm_init_t)
5107 dlsym(adev->adm_lib, "adm_init");
5108 adev->adm_deinit = (adm_deinit_t)
5109 dlsym(adev->adm_lib, "adm_deinit");
5110 adev->adm_register_input_stream = (adm_register_input_stream_t)
5111 dlsym(adev->adm_lib, "adm_register_input_stream");
5112 adev->adm_register_output_stream = (adm_register_output_stream_t)
5113 dlsym(adev->adm_lib, "adm_register_output_stream");
5114 adev->adm_deregister_stream = (adm_deregister_stream_t)
5115 dlsym(adev->adm_lib, "adm_deregister_stream");
5116 adev->adm_request_focus = (adm_request_focus_t)
5117 dlsym(adev->adm_lib, "adm_request_focus");
5118 adev->adm_abandon_focus = (adm_abandon_focus_t)
5119 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005120 adev->adm_set_config = (adm_set_config_t)
5121 dlsym(adev->adm_lib, "adm_set_config");
5122 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5123 dlsym(adev->adm_lib, "adm_request_focus_v2");
5124 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5125 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5126 adev->adm_on_routing_change = (adm_on_routing_change_t)
5127 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005128 }
5129 }
5130
Mingming Yin514a8bc2014-07-29 15:22:21 -07005131 adev->bt_wb_speech_enabled = false;
5132
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005133 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134 *device = &adev->device.common;
5135
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305136 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5137 &adev->streams_output_cfg_list,
5138 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005139
Kiran Kandi910e1862013-10-29 13:29:42 -07005140 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005141
5142 char value[PROPERTY_VALUE_MAX];
5143 int trial;
5144 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5145 trial = atoi(value);
5146 if (period_size_is_plausible_for_low_latency(trial)) {
5147 pcm_config_low_latency.period_size = trial;
5148 pcm_config_low_latency.start_threshold = trial / 4;
5149 pcm_config_low_latency.avail_min = trial / 4;
5150 configured_low_latency_capture_period_size = trial;
5151 }
5152 }
5153 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5154 trial = atoi(value);
5155 if (period_size_is_plausible_for_low_latency(trial)) {
5156 configured_low_latency_capture_period_size = trial;
5157 }
5158 }
5159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005160 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5161 af_period_multiplier = atoi(value);
5162 if (af_period_multiplier < 0)
5163 af_period_multiplier = 2;
5164 else if (af_period_multiplier > 4)
5165 af_period_multiplier = 4;
5166
5167 ALOGV("new period_multiplier = %d", af_period_multiplier);
5168 }
5169
vivek mehta446c3962015-09-14 10:57:35 -07005170 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005171 pthread_mutex_unlock(&adev_init_lock);
5172
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005173 if (adev->adm_init)
5174 adev->adm_data = adev->adm_init();
5175
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305176 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305177 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005178 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005179 return 0;
5180}
5181
5182static struct hw_module_methods_t hal_module_methods = {
5183 .open = adev_open,
5184};
5185
5186struct audio_module HAL_MODULE_INFO_SYM = {
5187 .common = {
5188 .tag = HARDWARE_MODULE_TAG,
5189 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5190 .hal_api_version = HARDWARE_HAL_API_VERSION,
5191 .id = AUDIO_HARDWARE_MODULE_ID,
5192 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005193 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194 .methods = &hal_module_methods,
5195 },
5196};