blob: 8881ff195f11e8e2e9bb5d296b18d8d5a38a5299 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, 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 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530609static void check_and_set_asrc_mode(struct audio_device *adev,
610 struct audio_usecase *uc_info,
611 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612{
613 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530614 int i, num_new_devices = 0;
615 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
616 /*
617 *Split snd device for new combo use case
618 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
619 */
620 if (platform_split_snd_device(adev->platform,
621 snd_device,
622 &num_new_devices,
623 split_new_snd_devices) == 0) {
624 for (i = 0; i < num_new_devices; i++)
625 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
626 } else {
627 int new_backend_idx = platform_get_backend_index(snd_device);
628 if (((new_backend_idx == HEADPHONE_BACKEND) ||
629 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
630 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
636 int i, num_devices, ret = 0;
637 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530638
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530639 list_for_each(node, &adev->usecase_list) {
640 uc = node_to_item(node, struct audio_usecase, list);
641 curr_out = (struct stream_out*) uc->stream.out;
642 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
643 /*
644 *Split snd device for existing combo use case
645 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
646 */
647 ret = platform_split_snd_device(adev->platform,
648 uc->out_snd_device,
649 &num_devices,
650 split_snd_devices);
651 if (ret < 0 || num_devices == 0) {
652 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
653 split_snd_devices[0] = uc->out_snd_device;
654 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800655 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530656 for (i = 0; i < num_devices; i++) {
657 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
658 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
659 if((new_backend_idx == HEADPHONE_BACKEND) &&
660 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
661 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
662 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
663 __func__);
664 enable_asrc_mode(adev);
665 break;
666 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
667 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
668 (usecase_backend_idx == HEADPHONE_BACKEND)) {
669 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
670 __func__);
671 disable_audio_route(adev, uc);
672 disable_snd_device(adev, uc->out_snd_device);
673 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
674 if (new_backend_idx == DSD_NATIVE_BACKEND)
675 audio_route_apply_and_update_path(adev->audio_route,
676 "hph-true-highquality-mode");
677 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
678 (curr_out->bit_width >= 24))
679 audio_route_apply_and_update_path(adev->audio_route,
680 "hph-highquality-mode");
681 enable_asrc_mode(adev);
682 enable_snd_device(adev, uc->out_snd_device);
683 enable_audio_route(adev, uc);
684 break;
685 }
686 }
687 // reset split devices count
688 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800689 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530690 if (adev->asrc_mode_enabled)
691 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530692 }
693 }
694 }
695}
696
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700697int pcm_ioctl(struct pcm *pcm, int request, ...)
698{
699 va_list ap;
700 void * arg;
701 int pcm_fd = *(int*)pcm;
702
703 va_start(ap, request);
704 arg = va_arg(ap, void *);
705 va_end(ap);
706
707 return ioctl(pcm_fd, request, arg);
708}
709
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700710int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700714 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800715
716 if (usecase == NULL)
717 return -EINVAL;
718
719 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
720
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800721 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800723 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800725
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800726#ifdef DS1_DOLBY_DAP_ENABLED
727 audio_extn_dolby_set_dmid(adev);
728 audio_extn_dolby_set_endpoint(adev);
729#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700730 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700731 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530732 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700733 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530734 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800735 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700736 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700737 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700738 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800739 ALOGV("%s: exit", __func__);
740 return 0;
741}
742
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700743int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700744 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800745{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700747 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800748
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530749 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800750 return -EINVAL;
751
752 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 if (usecase->type == PCM_CAPTURE)
754 snd_device = usecase->in_snd_device;
755 else
756 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800757 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700758 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700759 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700760 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700761 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530762 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763 ALOGV("%s: exit", __func__);
764 return 0;
765}
766
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700767int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700768 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530770 int i, num_devices = 0;
771 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
773
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800774 if (snd_device < SND_DEVICE_MIN ||
775 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800776 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800777 return -EINVAL;
778 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700779
780 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700781
782 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
783 ALOGE("%s: Invalid sound device returned", __func__);
784 return -EINVAL;
785 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700786 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700787 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700788 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 return 0;
790 }
791
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530792
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700793 if (audio_extn_spkr_prot_is_enabled())
794 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700795
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800796 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
797 audio_extn_spkr_prot_is_enabled()) {
798 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700799 adev->snd_dev_ref_cnt[snd_device]--;
800 return -EINVAL;
801 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200802 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800803 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200805 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800806 return -EINVAL;
807 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700808 } else if (platform_split_snd_device(adev->platform,
809 snd_device,
810 &num_devices,
811 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530812 for (i = 0; i < num_devices; i++) {
813 enable_snd_device(adev, new_snd_devices[i]);
814 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800815 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700816 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530817
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530818
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530819 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
820 (audio_extn_a2dp_start_playback() < 0)) {
821 ALOGE(" fail to configure A2dp control path ");
822 return -EINVAL;
823 }
824
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700825 /* due to the possibility of calibration overwrite between listen
826 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700827 audio_extn_sound_trigger_update_device_status(snd_device,
828 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530829 audio_extn_listen_update_device_status(snd_device,
830 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700831 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700832 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700833 audio_extn_sound_trigger_update_device_status(snd_device,
834 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530835 audio_extn_listen_update_device_status(snd_device,
836 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700837 return -EINVAL;
838 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300839 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700840 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530841
842 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
843 !adev->native_playback_enabled &&
844 audio_is_true_native_stream_active(adev)) {
845 ALOGD("%s: %d: napb: enabling native mode in hardware",
846 __func__, __LINE__);
847 audio_route_apply_and_update_path(adev->audio_route,
848 "true-native-mode");
849 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800852 return 0;
853}
854
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700855int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700856 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530858 int i, num_devices = 0;
859 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700860 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
861
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800862 if (snd_device < SND_DEVICE_MIN ||
863 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800864 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800865 return -EINVAL;
866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
868 ALOGE("%s: device ref cnt is already 0", __func__);
869 return -EINVAL;
870 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700871
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700873
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700874 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
875 ALOGE("%s: Invalid sound device returned", __func__);
876 return -EINVAL;
877 }
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700880 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530881
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800882 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
883 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700884 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700885 } else if (platform_split_snd_device(adev->platform,
886 snd_device,
887 &num_devices,
888 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530889 for (i = 0; i < num_devices; i++) {
890 disable_snd_device(adev, new_snd_devices[i]);
891 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300892 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700893 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300894 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700895
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530896 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
897 audio_extn_a2dp_stop_playback();
898
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700899 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530900 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530901 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
902 adev->native_playback_enabled) {
903 ALOGD("%s: %d: napb: disabling native mode in hardware",
904 __func__, __LINE__);
905 audio_route_reset_and_update_path(adev->audio_route,
906 "true-native-mode");
907 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530908 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
909 adev->asrc_mode_enabled) {
910 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530911 disable_asrc_mode(adev);
912 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530913 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530914
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200915 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700916 audio_extn_sound_trigger_update_device_status(snd_device,
917 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530918 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800919 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922 return 0;
923}
924
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700925/*
926 legend:
927 uc - existing usecase
928 new_uc - new usecase
929 d1, d11, d2 - SND_DEVICE enums
930 a1, a2 - corresponding ANDROID device enums
931 B1, B2 - backend strings
932
933case 1
934 uc->dev d1 (a1) B1
935 new_uc->dev d1 (a1), d2 (a2) B1, B2
936
937 resolution: disable and enable uc->dev on d1
938
939case 2
940 uc->dev d1 (a1) B1
941 new_uc->dev d11 (a1) B1
942
943 resolution: need to switch uc since d1 and d11 are related
944 (e.g. speaker and voice-speaker)
945 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
946
947case 3
948 uc->dev d1 (a1) B1
949 new_uc->dev d2 (a2) B2
950
951 resolution: no need to switch uc
952
953case 4
954 uc->dev d1 (a1) B1
955 new_uc->dev d2 (a2) B1
956
957 resolution: disable enable uc-dev on d2 since backends match
958 we cannot enable two streams on two different devices if they
959 share the same backend. e.g. if offload is on speaker device using
960 QUAD_MI2S backend and a low-latency stream is started on voice-handset
961 using the same backend, offload must also be switched to voice-handset.
962
963case 5
964 uc->dev d1 (a1) B1
965 new_uc->dev d1 (a1), d2 (a2) B1
966
967 resolution: disable enable uc-dev on d2 since backends match
968 we cannot enable two streams on two different devices if they
969 share the same backend.
970
971case 6
972 uc->dev d1 (a1) B1
973 new_uc->dev d2 (a1) B2
974
975 resolution: no need to switch
976
977case 7
978 uc->dev d1 (a1), d2 (a2) B1, B2
979 new_uc->dev d1 (a1) B1
980
981 resolution: no need to switch
982
983*/
984static snd_device_t derive_playback_snd_device(void * platform,
985 struct audio_usecase *uc,
986 struct audio_usecase *new_uc,
987 snd_device_t new_snd_device)
988{
989 audio_devices_t a1 = uc->stream.out->devices;
990 audio_devices_t a2 = new_uc->stream.out->devices;
991
992 snd_device_t d1 = uc->out_snd_device;
993 snd_device_t d2 = new_snd_device;
994
995 // Treat as a special case when a1 and a2 are not disjoint
996 if ((a1 != a2) && (a1 & a2)) {
997 snd_device_t d3[2];
998 int num_devices = 0;
999 int ret = platform_split_snd_device(platform,
1000 popcount(a1) > 1 ? d1 : d2,
1001 &num_devices,
1002 d3);
1003 if (ret < 0) {
1004 if (ret != -ENOSYS) {
1005 ALOGW("%s failed to split snd_device %d",
1006 __func__,
1007 popcount(a1) > 1 ? d1 : d2);
1008 }
1009 goto end;
1010 }
1011
1012 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1013 // But if it does happen, we need to give priority to d2 if
1014 // the combo devices active on the existing usecase share a backend.
1015 // This is because we cannot have a usecase active on a combo device
1016 // and a new usecase requests one device in this combo pair.
1017 if (platform_check_backends_match(d3[0], d3[1])) {
1018 return d2; // case 5
1019 } else {
1020 return d1; // case 1
1021 }
1022 } else {
1023 if (platform_check_backends_match(d1, d2)) {
1024 return d2; // case 2, 4
1025 } else {
1026 return d1; // case 6, 3
1027 }
1028 }
1029
1030end:
1031 return d2; // return whatever was calculated before.
1032}
1033
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301035 struct audio_usecase *uc_info,
1036 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037{
1038 struct listnode *node;
1039 struct audio_usecase *usecase;
1040 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301041 snd_device_t uc_derive_snd_device;
1042 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001044 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301045 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 /*
1047 * This function is to make sure that all the usecases that are active on
1048 * the hardware codec backend are always routed to any one device that is
1049 * handled by the hardware codec.
1050 * For example, if low-latency and deep-buffer usecases are currently active
1051 * on speaker and out_set_parameters(headset) is received on low-latency
1052 * output, then we have to make sure deep-buffer is also switched to headset,
1053 * because of the limitation that both the devices cannot be enabled
1054 * at the same time as they share the same backend.
1055 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001056 /*
1057 * This call is to check if we need to force routing for a particular stream
1058 * If there is a backend configuration change for the device when a
1059 * new stream starts, then ADM needs to be closed and re-opened with the new
1060 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001061 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001062 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001063 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1064 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301065 /* For a2dp device reconfigure all active sessions
1066 * with new AFE encoder format based on a2dp state
1067 */
1068 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1069 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1070 audio_extn_a2dp_is_force_device_switch()) {
1071 force_routing = true;
1072 force_restart_session = true;
1073 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301074 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1075
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001077 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001078 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1080 switch_device[i] = false;
1081
1082 list_for_each(node, &adev->usecase_list) {
1083 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001084
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301085 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1086 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301087 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301088 platform_get_snd_device_name(usecase->out_snd_device),
1089 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301090 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1091 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1092 usecase, uc_info, snd_device);
1093 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1094 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1095 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1096 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1097 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1098 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1099 ((force_restart_session) ||
1100 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301101 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1102 __func__, use_case_table[usecase->id],
1103 platform_get_snd_device_name(usecase->out_snd_device));
1104 disable_audio_route(adev, usecase);
1105 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301106 /* Enable existing usecase on derived playback device */
1107 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301108 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 }
1111 }
1112
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301113 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1114 num_uc_to_switch);
1115
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001117 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301119 /* Make sure the previous devices to be disabled first and then enable the
1120 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 list_for_each(node, &adev->usecase_list) {
1122 usecase = node_to_item(node, struct audio_usecase, list);
1123 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001124 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 }
1126 }
1127
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001128 list_for_each(node, &adev->usecase_list) {
1129 usecase = node_to_item(node, struct audio_usecase, list);
1130 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301131 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001132 }
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 /* Re-route all the usecases on the shared backend other than the
1136 specified usecase to new snd devices */
1137 list_for_each(node, &adev->usecase_list) {
1138 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301139 /* Update the out_snd_device only before enabling the audio route */
1140 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301141 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301142 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301143 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301144 use_case_table[usecase->id],
1145 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001146 /* Update voc calibration before enabling VoIP route */
1147 if (usecase->type == VOIP_CALL)
1148 status = platform_switch_voice_call_device_post(adev->platform,
1149 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001150 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301151 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301152 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153 }
1154 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155 }
1156}
1157
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301158static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001159 struct audio_usecase *uc_info,
1160 snd_device_t snd_device)
1161{
1162 struct listnode *node;
1163 struct audio_usecase *usecase;
1164 bool switch_device[AUDIO_USECASE_MAX];
1165 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301166 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001167 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301169 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1170 snd_device);
1171 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301172
1173 /*
1174 * Make sure out devices is checked against out codec backend device and
1175 * also in devices against in codec backend. Checking out device against in
1176 * codec backend or vice versa causes issues.
1177 */
1178 if (uc_info->type == PCM_CAPTURE)
1179 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001180 /*
1181 * This function is to make sure that all the active capture usecases
1182 * are always routed to the same input sound device.
1183 * For example, if audio-record and voice-call usecases are currently
1184 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1185 * is received for voice call then we have to make sure that audio-record
1186 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1187 * because of the limitation that two devices cannot be enabled
1188 * at the same time if they share the same backend.
1189 */
1190 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1191 switch_device[i] = false;
1192
1193 list_for_each(node, &adev->usecase_list) {
1194 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301195 /*
1196 * TODO: Enhance below condition to handle BT sco/USB multi recording
1197 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001198 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001199 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301200 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301201 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301202 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301203 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001204 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001205 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1206 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001207 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001208 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001209 switch_device[usecase->id] = true;
1210 num_uc_to_switch++;
1211 }
1212 }
1213
1214 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001215 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301217 /* Make sure the previous devices to be disabled first and then enable the
1218 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001219 list_for_each(node, &adev->usecase_list) {
1220 usecase = node_to_item(node, struct audio_usecase, list);
1221 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001223 }
1224 }
1225
1226 list_for_each(node, &adev->usecase_list) {
1227 usecase = node_to_item(node, struct audio_usecase, list);
1228 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001229 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 }
1231 }
1232
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001233 /* Re-route all the usecases on the shared backend other than the
1234 specified usecase to new snd devices */
1235 list_for_each(node, &adev->usecase_list) {
1236 usecase = node_to_item(node, struct audio_usecase, list);
1237 /* Update the in_snd_device only before enabling the audio route */
1238 if (switch_device[usecase->id] ) {
1239 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001240 if (usecase->type != VOICE_CALL) {
1241 /* Update voc calibration before enabling VoIP route */
1242 if (usecase->type == VOIP_CALL)
1243 status = platform_switch_voice_call_device_post(adev->platform,
1244 usecase->out_snd_device,
1245 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301246 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001247 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001248 }
1249 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001250 }
1251}
1252
Mingming Yin3a941d42016-02-17 18:08:05 -08001253static void reset_hdmi_sink_caps(struct stream_out *out) {
1254 int i = 0;
1255
1256 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1257 out->supported_channel_masks[i] = 0;
1258 }
1259 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1260 out->supported_formats[i] = 0;
1261 }
1262 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1263 out->supported_sample_rates[i] = 0;
1264 }
1265}
1266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001268static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269{
Mingming Yin3a941d42016-02-17 18:08:05 -08001270 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001271 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Mingming Yin3a941d42016-02-17 18:08:05 -08001273 reset_hdmi_sink_caps(out);
1274
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001275 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001276 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001277 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001278 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001279 }
1280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001283 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001284 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001285 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1286 case 6:
1287 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1291 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1292 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293 break;
1294 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001295 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001296 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 break;
1298 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001299
1300 // check channel format caps
1301 i = 0;
1302 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1303 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1304 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1305 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1306 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1307 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1308 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1309 }
1310
1311 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1312 ALOGV(":%s HDMI supports DTS format", __func__);
1313 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1314 }
1315
1316 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1317 ALOGV(":%s HDMI supports DTS HD format", __func__);
1318 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1319 }
1320
1321
1322 // check sample rate caps
1323 i = 0;
1324 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1325 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1326 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1327 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1328 }
1329 }
1330
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001331 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332}
1333
Alexy Josephb1379942016-01-29 15:49:38 -08001334audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001335 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001336{
1337 struct audio_usecase *usecase;
1338 struct listnode *node;
1339
1340 list_for_each(node, &adev->usecase_list) {
1341 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001342 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001343 ALOGV("%s: usecase id %d", __func__, usecase->id);
1344 return usecase->id;
1345 }
1346 }
1347 return USECASE_INVALID;
1348}
1349
Alexy Josephb1379942016-01-29 15:49:38 -08001350struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001351 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352{
1353 struct audio_usecase *usecase;
1354 struct listnode *node;
1355
1356 list_for_each(node, &adev->usecase_list) {
1357 usecase = node_to_item(node, struct audio_usecase, list);
1358 if (usecase->id == uc_id)
1359 return usecase;
1360 }
1361 return NULL;
1362}
1363
Dhananjay Kumard4833242016-10-06 22:09:12 +05301364struct stream_in *get_next_active_input(const struct audio_device *adev)
1365{
1366 struct audio_usecase *usecase;
1367 struct listnode *node;
1368
1369 list_for_each_reverse(node, &adev->usecase_list) {
1370 usecase = node_to_item(node, struct audio_usecase, list);
1371 if (usecase->type == PCM_CAPTURE)
1372 return usecase->stream.in;
1373 }
1374 return NULL;
1375}
1376
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301377/*
1378 * is a true native playback active
1379 */
1380bool audio_is_true_native_stream_active(struct audio_device *adev)
1381{
1382 bool active = false;
1383 int i = 0;
1384 struct listnode *node;
1385
1386 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1387 ALOGV("%s:napb: not in true mode or non hdphones device",
1388 __func__);
1389 active = false;
1390 goto exit;
1391 }
1392
1393 list_for_each(node, &adev->usecase_list) {
1394 struct audio_usecase *uc;
1395 uc = node_to_item(node, struct audio_usecase, list);
1396 struct stream_out *curr_out =
1397 (struct stream_out*) uc->stream.out;
1398
1399 if (curr_out && PCM_PLAYBACK == uc->type) {
1400 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1401 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1402 uc->id, curr_out->sample_rate,
1403 curr_out->bit_width,
1404 platform_get_snd_device_name(uc->out_snd_device));
1405
1406 if (is_offload_usecase(uc->id) &&
1407 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1408 active = true;
1409 ALOGD("%s:napb:native stream detected", __func__);
1410 }
1411 }
1412 }
1413exit:
1414 return active;
1415}
1416
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301417/*
1418 * if native DSD playback active
1419 */
1420bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1421{
1422 bool active = false;
1423 struct listnode *node = NULL;
1424 struct audio_usecase *uc = NULL;
1425 struct stream_out *curr_out = NULL;
1426
1427 list_for_each(node, &adev->usecase_list) {
1428 uc = node_to_item(node, struct audio_usecase, list);
1429 curr_out = (struct stream_out*) uc->stream.out;
1430
1431 if (curr_out && PCM_PLAYBACK == uc->type &&
1432 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1433 active = true;
1434 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301435 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301436 }
1437 }
1438 return active;
1439}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301440
1441static bool force_device_switch(struct audio_usecase *usecase)
1442{
1443 bool ret = false;
1444 bool is_it_true_mode = false;
1445
1446 if (is_offload_usecase(usecase->id) &&
1447 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001448 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1449 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1450 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301451 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1452 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1453 (!is_it_true_mode && adev->native_playback_enabled)){
1454 ret = true;
1455 ALOGD("napb: time to toggle native mode");
1456 }
1457 }
1458
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301459 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301460 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1461 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301462 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001463 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301464 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301465 ALOGD("Force a2dp device switch to update new encoder config");
1466 ret = true;
1467 }
1468
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301469 return ret;
1470}
1471
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001472int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001474 snd_device_t out_snd_device = SND_DEVICE_NONE;
1475 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 struct audio_usecase *usecase = NULL;
1477 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001478 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001479 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001480 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301483 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1484
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 usecase = get_usecase_from_list(adev, uc_id);
1486 if (usecase == NULL) {
1487 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1488 return -EINVAL;
1489 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001491 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001492 (usecase->type == VOIP_CALL) ||
1493 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301494 if(usecase->stream.out == NULL) {
1495 ALOGE("%s: stream.out is NULL", __func__);
1496 return -EINVAL;
1497 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001498 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001499 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001500 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 usecase->devices = usecase->stream.out->devices;
1502 } else {
1503 /*
1504 * If the voice call is active, use the sound devices of voice call usecase
1505 * so that it would not result any device switch. All the usecases will
1506 * be switched to new device when select_devices() is called for voice call
1507 * usecase. This is to avoid switching devices for voice call when
1508 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001509 * choose voice call device only if the use case device is
1510 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001511 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001512 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001513 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001514 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001515 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1516 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301517 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1518 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001519 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 in_snd_device = vc_usecase->in_snd_device;
1521 out_snd_device = vc_usecase->out_snd_device;
1522 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001523 } else if (voice_extn_compress_voip_is_active(adev)) {
1524 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001525 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001526 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1527 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001528 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001529 in_snd_device = voip_usecase->in_snd_device;
1530 out_snd_device = voip_usecase->out_snd_device;
1531 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001532 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001533 hfp_ucid = audio_extn_hfp_get_usecase();
1534 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001535 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001536 in_snd_device = hfp_usecase->in_snd_device;
1537 out_snd_device = hfp_usecase->out_snd_device;
1538 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001539 }
1540 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301541 if (usecase->stream.out == NULL) {
1542 ALOGE("%s: stream.out is NULL", __func__);
1543 return -EINVAL;
1544 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001545 usecase->devices = usecase->stream.out->devices;
1546 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001547 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001548 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001549 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001550 if (usecase->stream.out == adev->primary_output &&
1551 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001552 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001553 select_devices(adev, adev->active_input->usecase);
1554 }
1555 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301557 if (usecase->stream.in == NULL) {
1558 ALOGE("%s: stream.in is NULL", __func__);
1559 return -EINVAL;
1560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 usecase->devices = usecase->stream.in->device;
1562 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001563 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001564 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001565 if (adev->active_input &&
1566 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301567 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1568 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1569 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001570 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001571 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001572 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1573 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001574 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001575 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001576 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 }
1578 }
1579
1580 if (out_snd_device == usecase->out_snd_device &&
1581 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301582
1583 if (!force_device_switch(usecase))
1584 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 }
1586
sangwoobc677242013-08-08 16:53:43 +09001587 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001588 out_snd_device, platform_get_snd_device_name(out_snd_device),
1589 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 /*
1592 * Limitation: While in call, to do a device switch we need to disable
1593 * and enable both RX and TX devices though one of them is same as current
1594 * device.
1595 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001596 if ((usecase->type == VOICE_CALL) &&
1597 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1598 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001599 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001600 }
1601
1602 if (((usecase->type == VOICE_CALL) ||
1603 (usecase->type == VOIP_CALL)) &&
1604 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1605 /* Disable sidetone only if voice/voip call already exists */
1606 if (voice_is_call_state_active(adev) ||
1607 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001608 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001609
1610 /* Disable aanc only if voice call exists */
1611 if (voice_is_call_state_active(adev))
1612 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001613 }
1614
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001615 /* Disable current sound devices */
1616 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001617 disable_audio_route(adev, usecase);
1618 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 }
1620
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001622 disable_audio_route(adev, usecase);
1623 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
1625
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001626 /* Applicable only on the targets that has external modem.
1627 * New device information should be sent to modem before enabling
1628 * the devices to reduce in-call device switch time.
1629 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001630 if ((usecase->type == VOICE_CALL) &&
1631 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1632 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001633 status = platform_switch_voice_call_enable_device_config(adev->platform,
1634 out_snd_device,
1635 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001636 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001637
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001638 /* Enable new sound devices */
1639 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001640 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301641 if (platform_check_codec_asrc_support(adev->platform))
1642 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001643 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 }
1645
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001646 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301647 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001648 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001649 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001650
Avinash Vaish71a8b972014-07-24 15:36:33 +05301651 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001652 status = platform_switch_voice_call_device_post(adev->platform,
1653 out_snd_device,
1654 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301655 enable_audio_route_for_voice_usecases(adev, usecase);
1656 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001657
sangwoo170731f2013-06-08 15:36:36 +09001658 usecase->in_snd_device = in_snd_device;
1659 usecase->out_snd_device = out_snd_device;
1660
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301661 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1662 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301663 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001664 if ((24 == usecase->stream.out->bit_width) &&
1665 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1666 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1667 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1668 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1669 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1670 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1671 /*
1672 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1673 * configured device sample rate, if not update the COPP rate to be equal to the
1674 * device sample rate, else open COPP at stream sample rate
1675 */
1676 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1677 usecase->stream.out->sample_rate,
1678 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301679 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1680 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001681 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1682 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1683 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1684 }
1685
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001686 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001687 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001688 audio_extn_gef_notify_device_config(
1689 usecase->stream.out->devices,
1690 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001691 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001692 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001693 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301694 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001695 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001696
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001697 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001698 /* Enable aanc only if voice call exists */
1699 if (voice_is_call_state_active(adev))
1700 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1701
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001702 /* Enable sidetone only if other voice/voip call already exists */
1703 if (voice_is_call_state_active(adev) ||
1704 voice_extn_compress_voip_is_started(adev))
1705 voice_set_sidetone(adev, out_snd_device, true);
1706 }
1707
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001708 /* Applicable only on the targets that has external modem.
1709 * Enable device command should be sent to modem only after
1710 * enabling voice call mixer controls
1711 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001712 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001713 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1714 out_snd_device,
1715 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301716 ALOGD("%s: done",__func__);
1717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 return status;
1719}
1720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721static int stop_input_stream(struct stream_in *in)
1722{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301723 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724 struct audio_usecase *uc_info;
1725 struct audio_device *adev = in->dev;
1726
Eric Laurent994a6932013-07-17 11:51:42 -07001727 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 uc_info = get_usecase_from_list(adev, in->usecase);
1730 if (uc_info == NULL) {
1731 ALOGE("%s: Could not find the usecase (%d) in the list",
1732 __func__, in->usecase);
1733 return -EINVAL;
1734 }
1735
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001736 /* Close in-call recording streams */
1737 voice_check_and_stop_incall_rec_usecase(adev, in);
1738
Eric Laurent150dbfe2013-02-27 14:31:02 -08001739 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001740 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741
1742 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001743 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001745 list_remove(&uc_info->list);
1746 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001748 adev->active_input = get_next_active_input(adev);
1749
Eric Laurent994a6932013-07-17 11:51:42 -07001750 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751 return ret;
1752}
1753
1754int start_input_stream(struct stream_in *in)
1755{
1756 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001757 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 struct audio_usecase *uc_info;
1759 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301760 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761
Mingming Yin2664a5b2015-09-03 10:53:11 -07001762 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1763 if (get_usecase_from_list(adev, usecase) == NULL)
1764 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301765 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1766 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001767
Naresh Tanniru80659832014-06-04 18:17:56 +05301768
1769 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301770 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301771 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301772 goto error_config;
1773 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301774
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001775 /* Check if source matches incall recording usecase criteria */
1776 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1777 if (ret)
1778 goto error_config;
1779 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001780 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1781
1782 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1783 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1784 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001785 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001786 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001787
Eric Laurentb23d5282013-05-14 15:27:20 -07001788 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 if (in->pcm_device_id < 0) {
1790 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1791 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001792 ret = -EINVAL;
1793 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795
1796 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001798
1799 if (!uc_info) {
1800 ret = -ENOMEM;
1801 goto error_config;
1802 }
1803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 uc_info->id = in->usecase;
1805 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001806 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807 uc_info->devices = in->device;
1808 uc_info->in_snd_device = SND_DEVICE_NONE;
1809 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001811 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301812 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1813 adev->perf_lock_opts,
1814 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301817 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1818 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001819
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301820 if (audio_extn_cin_attached_usecase(in->usecase)) {
1821 ret = audio_extn_cin_start_input_stream(in);
1822 if (ret)
1823 goto error_open;
1824 else
1825 goto done_open;
1826 }
1827
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001828 unsigned int flags = PCM_IN;
1829 unsigned int pcm_open_retry_count = 0;
1830
1831 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1832 flags |= PCM_MMAP | PCM_NOIRQ;
1833 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001834 } else if (in->realtime) {
1835 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001836 }
1837
1838 while (1) {
1839 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1840 flags, &in->config);
1841 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1842 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1843 if (in->pcm != NULL) {
1844 pcm_close(in->pcm);
1845 in->pcm = NULL;
1846 }
1847 if (pcm_open_retry_count-- == 0) {
1848 ret = -EIO;
1849 goto error_open;
1850 }
1851 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1852 continue;
1853 }
1854 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001856
1857 ALOGV("%s: pcm_prepare", __func__);
1858 ret = pcm_prepare(in->pcm);
1859 if (ret < 0) {
1860 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1861 pcm_close(in->pcm);
1862 in->pcm = NULL;
1863 goto error_open;
1864 }
1865
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001866 register_in_stream(in);
1867 if (in->realtime) {
1868 ret = pcm_start(in->pcm);
1869 if (ret < 0)
1870 goto error_open;
1871 }
1872
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301873done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301874 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001875 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001876
Eric Laurentc8400632013-02-14 19:04:54 -08001877 return ret;
1878
1879error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301880 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001882error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301883 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301884 /*
1885 * sleep 50ms to allow sufficient time for kernel
1886 * drivers to recover incases like SSR.
1887 */
1888 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001890
1891 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892}
1893
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001894void lock_input_stream(struct stream_in *in)
1895{
1896 pthread_mutex_lock(&in->pre_lock);
1897 pthread_mutex_lock(&in->lock);
1898 pthread_mutex_unlock(&in->pre_lock);
1899}
1900
1901void lock_output_stream(struct stream_out *out)
1902{
1903 pthread_mutex_lock(&out->pre_lock);
1904 pthread_mutex_lock(&out->lock);
1905 pthread_mutex_unlock(&out->pre_lock);
1906}
1907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001908/* must be called with out->lock locked */
1909static int send_offload_cmd_l(struct stream_out* out, int command)
1910{
1911 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1912
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001913 if (!cmd) {
1914 ALOGE("failed to allocate mem for command 0x%x", command);
1915 return -ENOMEM;
1916 }
1917
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001918 ALOGVV("%s %d", __func__, command);
1919
1920 cmd->cmd = command;
1921 list_add_tail(&out->offload_cmd_list, &cmd->node);
1922 pthread_cond_signal(&out->offload_cond);
1923 return 0;
1924}
1925
1926/* must be called iwth out->lock locked */
1927static void stop_compressed_output_l(struct stream_out *out)
1928{
1929 out->offload_state = OFFLOAD_STATE_IDLE;
1930 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932 if (out->compr != NULL) {
1933 compress_stop(out->compr);
1934 while (out->offload_thread_blocked) {
1935 pthread_cond_wait(&out->cond, &out->lock);
1936 }
1937 }
1938}
1939
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001940bool is_offload_usecase(audio_usecase_t uc_id)
1941{
1942 unsigned int i;
1943 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1944 if (uc_id == offload_usecases[i])
1945 return true;
1946 }
1947 return false;
1948}
1949
Dhananjay Kumarac341582017-02-23 23:42:25 +05301950static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001951{
vivek mehta446c3962015-09-14 10:57:35 -07001952 audio_usecase_t ret_uc = USECASE_INVALID;
1953 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001954 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001955 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301956 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001957 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1958 else
1959 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001960
vivek mehta446c3962015-09-14 10:57:35 -07001961 pthread_mutex_lock(&adev->lock);
1962 if (get_usecase_from_list(adev, ret_uc) != NULL)
1963 ret_uc = USECASE_INVALID;
1964 pthread_mutex_unlock(&adev->lock);
1965
1966 return ret_uc;
1967 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001968
1969 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001970 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1971 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1972 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1973 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001974 break;
1975 }
1976 }
vivek mehta446c3962015-09-14 10:57:35 -07001977
1978 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1979 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001980}
1981
1982static void free_offload_usecase(struct audio_device *adev,
1983 audio_usecase_t uc_id)
1984{
vivek mehta446c3962015-09-14 10:57:35 -07001985 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001986 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001987
1988 if (!adev->multi_offload_enable)
1989 return;
1990
1991 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1992 if (offload_usecases[offload_uc_index] == uc_id) {
1993 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001994 break;
1995 }
1996 }
1997 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1998}
1999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002000static void *offload_thread_loop(void *context)
2001{
2002 struct stream_out *out = (struct stream_out *) context;
2003 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002004 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2007 set_sched_policy(0, SP_FOREGROUND);
2008 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2009
2010 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002011 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002012 for (;;) {
2013 struct offload_cmd *cmd = NULL;
2014 stream_callback_event_t event;
2015 bool send_callback = false;
2016
2017 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2018 __func__, list_empty(&out->offload_cmd_list),
2019 out->offload_state);
2020 if (list_empty(&out->offload_cmd_list)) {
2021 ALOGV("%s SLEEPING", __func__);
2022 pthread_cond_wait(&out->offload_cond, &out->lock);
2023 ALOGV("%s RUNNING", __func__);
2024 continue;
2025 }
2026
2027 item = list_head(&out->offload_cmd_list);
2028 cmd = node_to_item(item, struct offload_cmd, node);
2029 list_remove(item);
2030
2031 ALOGVV("%s STATE %d CMD %d out->compr %p",
2032 __func__, out->offload_state, cmd->cmd, out->compr);
2033
2034 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2035 free(cmd);
2036 break;
2037 }
2038
2039 if (out->compr == NULL) {
2040 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002041 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 pthread_cond_signal(&out->cond);
2043 continue;
2044 }
2045 out->offload_thread_blocked = true;
2046 pthread_mutex_unlock(&out->lock);
2047 send_callback = false;
2048 switch(cmd->cmd) {
2049 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002050 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002052 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 send_callback = true;
2054 event = STREAM_CBK_EVENT_WRITE_READY;
2055 break;
2056 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002057 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302058 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002059 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302060 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002061 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302062 if (ret < 0)
2063 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302064 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302065 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002066 compress_drain(out->compr);
2067 else
2068 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302069 if (ret != -ENETRESET) {
2070 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302071 pthread_mutex_lock(&out->lock);
2072 out->send_new_metadata = 1;
2073 out->send_next_track_params = true;
2074 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302075 event = STREAM_CBK_EVENT_DRAIN_READY;
2076 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2077 } else
2078 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 break;
2080 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002081 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002083 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 send_callback = true;
2085 event = STREAM_CBK_EVENT_DRAIN_READY;
2086 break;
2087 default:
2088 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2089 break;
2090 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002091 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002092 out->offload_thread_blocked = false;
2093 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002094 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002095 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002097 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 free(cmd);
2099 }
2100
2101 pthread_cond_signal(&out->cond);
2102 while (!list_empty(&out->offload_cmd_list)) {
2103 item = list_head(&out->offload_cmd_list);
2104 list_remove(item);
2105 free(node_to_item(item, struct offload_cmd, node));
2106 }
2107 pthread_mutex_unlock(&out->lock);
2108
2109 return NULL;
2110}
2111
2112static int create_offload_callback_thread(struct stream_out *out)
2113{
2114 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2115 list_init(&out->offload_cmd_list);
2116 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2117 offload_thread_loop, out);
2118 return 0;
2119}
2120
2121static int destroy_offload_callback_thread(struct stream_out *out)
2122{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002123 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 stop_compressed_output_l(out);
2125 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2126
2127 pthread_mutex_unlock(&out->lock);
2128 pthread_join(out->offload_thread, (void **) NULL);
2129 pthread_cond_destroy(&out->offload_cond);
2130
2131 return 0;
2132}
2133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134static int stop_output_stream(struct stream_out *out)
2135{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302136 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 struct audio_usecase *uc_info;
2138 struct audio_device *adev = out->dev;
2139
Eric Laurent994a6932013-07-17 11:51:42 -07002140 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 uc_info = get_usecase_from_list(adev, out->usecase);
2143 if (uc_info == NULL) {
2144 ALOGE("%s: Could not find the usecase (%d) in the list",
2145 __func__, out->usecase);
2146 return -EINVAL;
2147 }
2148
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002149 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302150 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002151 if (adev->visualizer_stop_output != NULL)
2152 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002153
2154 audio_extn_dts_remove_state_notifier_node(out->usecase);
2155
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002156 if (adev->offload_effects_stop_output != NULL)
2157 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2158 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002159
Eric Laurent150dbfe2013-02-27 14:31:02 -08002160 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002161 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002162
2163 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002164 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002166 list_remove(&uc_info->list);
2167 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002169 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302170 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002171 ALOGV("Disable passthrough , reset mixer to pcm");
2172 /* NO_PASSTHROUGH */
2173 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002174 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002175 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2176 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002177
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302178 /* Must be called after removing the usecase from list */
2179 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302180 audio_extn_keep_alive_start();
2181
Eric Laurent994a6932013-07-17 11:51:42 -07002182 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 return ret;
2184}
2185
2186int start_output_stream(struct stream_out *out)
2187{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 struct audio_usecase *uc_info;
2190 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302191 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002192 char mixer_ctl_name[128];
2193 struct mixer_ctl *ctl = NULL;
2194 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002196 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2197 ret = -EINVAL;
2198 goto error_config;
2199 }
2200
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302201 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2202 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2203 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302204
Naresh Tanniru80659832014-06-04 18:17:56 +05302205 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302206 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302207 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302208 goto error_config;
2209 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302210
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302211 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2212 if (!audio_extn_a2dp_is_ready()) {
2213 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2214 //combo usecase just by pass a2dp
2215 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2216 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2217 } else {
2218 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2219 ret = -EAGAIN;
2220 goto error_config;
2221 }
2222 }
2223 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002224 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 if (out->pcm_device_id < 0) {
2226 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2227 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002228 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002229 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 }
2231
2232 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002233
2234 if (!uc_info) {
2235 ret = -ENOMEM;
2236 goto error_config;
2237 }
2238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 uc_info->id = out->usecase;
2240 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002241 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002242 uc_info->devices = out->devices;
2243 uc_info->in_snd_device = SND_DEVICE_NONE;
2244 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002245 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302247 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2248 adev->perf_lock_opts,
2249 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302250
2251 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2252 audio_extn_keep_alive_stop();
2253 if (audio_extn_passthru_is_enabled() &&
2254 audio_extn_passthru_is_passthrough_stream(out)) {
2255 audio_extn_passthru_on_start(out);
2256 audio_extn_passthru_update_stream_configuration(adev, out);
2257 }
2258 }
2259
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002260 select_devices(adev, out->usecase);
2261
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002262 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2263 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002264 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002265 unsigned int flags = PCM_OUT;
2266 unsigned int pcm_open_retry_count = 0;
2267 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2268 flags |= PCM_MMAP | PCM_NOIRQ;
2269 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002270 } else if (out->realtime) {
2271 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002272 } else
2273 flags |= PCM_MONOTONIC;
2274
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002275 if ((adev->vr_audio_mode_enabled) &&
2276 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2277 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2278 "PCM_Dev %d Topology", out->pcm_device_id);
2279 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2280 if (!ctl) {
2281 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2282 __func__, mixer_ctl_name);
2283 } else {
2284 //if success use ULLPP
2285 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2286 __func__, mixer_ctl_name, out->pcm_device_id);
2287 //There is a still a possibility that some sessions
2288 // that request for FAST|RAW when 3D audio is active
2289 //can go through ULLPP. Ideally we expects apps to
2290 //listen to audio focus and stop concurrent playback
2291 //Also, we will look for mode flag (voice_in_communication)
2292 //before enabling the realtime flag.
2293 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2294 }
2295 }
2296
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002297 while (1) {
2298 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2299 flags, &out->config);
2300 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2301 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2302 if (out->pcm != NULL) {
2303 pcm_close(out->pcm);
2304 out->pcm = NULL;
2305 }
2306 if (pcm_open_retry_count-- == 0) {
2307 ret = -EIO;
2308 goto error_open;
2309 }
2310 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2311 continue;
2312 }
2313 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002314 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002315
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002316 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2317 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002318
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002319 ALOGV("%s: pcm_prepare", __func__);
2320 if (pcm_is_ready(out->pcm)) {
2321 ret = pcm_prepare(out->pcm);
2322 if (ret < 0) {
2323 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2324 pcm_close(out->pcm);
2325 out->pcm = NULL;
2326 goto error_open;
2327 }
2328 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302329 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2330 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002332 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2333 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002335 out->compr = compress_open(adev->snd_card,
2336 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 COMPRESS_IN, &out->compr_config);
2338 if (out->compr && !is_compress_ready(out->compr)) {
2339 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2340 compress_close(out->compr);
2341 out->compr = NULL;
2342 ret = -EIO;
2343 goto error_open;
2344 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302345 /* compress_open sends params of the track, so reset the flag here */
2346 out->is_compr_metadata_avail = false;
2347
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 if (out->offload_callback)
2349 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002350
Fred Oh3f43e742015-03-04 18:42:34 -08002351 /* Since small bufs uses blocking writes, a write will be blocked
2352 for the default max poll time (20s) in the event of an SSR.
2353 Reduce the poll time to observe and deal with SSR faster.
2354 */
Ashish Jain5106d362016-05-11 19:23:33 +05302355 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002356 compress_set_max_poll_wait(out->compr, 1000);
2357 }
2358
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002359 audio_extn_dts_create_state_notifier_node(out->usecase);
2360 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2361 popcount(out->channel_mask),
2362 out->playback_started);
2363
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002364#ifdef DS1_DOLBY_DDP_ENABLED
2365 if (audio_extn_is_dolby_format(out->format))
2366 audio_extn_dolby_send_ddp_endp_params(adev);
2367#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302368 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2369 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002370 if (adev->visualizer_start_output != NULL)
2371 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2372 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302373 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002375 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002377
2378 if (ret == 0) {
2379 register_out_stream(out);
2380 if (out->realtime) {
2381 ret = pcm_start(out->pcm);
2382 if (ret < 0)
2383 goto error_open;
2384 }
2385 }
2386
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302387 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002388 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002389
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002390 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302392 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002394error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302395 /*
2396 * sleep 50ms to allow sufficient time for kernel
2397 * drivers to recover incases like SSR.
2398 */
2399 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002400 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401}
2402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403static int check_input_parameters(uint32_t sample_rate,
2404 audio_format_t format,
2405 int channel_count)
2406{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002407 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302409 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2410 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2411 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002412 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302413 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002414
2415 switch (channel_count) {
2416 case 1:
2417 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302418 case 3:
2419 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002420 case 6:
2421 break;
2422 default:
2423 ret = -EINVAL;
2424 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425
2426 switch (sample_rate) {
2427 case 8000:
2428 case 11025:
2429 case 12000:
2430 case 16000:
2431 case 22050:
2432 case 24000:
2433 case 32000:
2434 case 44100:
2435 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302436 case 96000:
2437 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 break;
2439 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002440 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 }
2442
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002443 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444}
2445
2446static size_t get_input_buffer_size(uint32_t sample_rate,
2447 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002448 int channel_count,
2449 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450{
2451 size_t size = 0;
2452
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002453 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2454 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002456 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002457 if (is_low_latency)
2458 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302459
2460 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002462 /* make sure the size is multiple of 32 bytes
2463 * At 48 kHz mono 16-bit PCM:
2464 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2465 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2466 */
2467 size += 0x1f;
2468 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002469
2470 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471}
2472
Ashish Jain058165c2016-09-28 23:18:48 +05302473static size_t get_output_period_size(uint32_t sample_rate,
2474 audio_format_t format,
2475 int channel_count,
2476 int duration /*in millisecs*/)
2477{
2478 size_t size = 0;
2479 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2480
2481 if ((duration == 0) || (sample_rate == 0) ||
2482 (bytes_per_sample == 0) || (channel_count == 0)) {
2483 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2484 bytes_per_sample, channel_count);
2485 return -EINVAL;
2486 }
2487
2488 size = (sample_rate *
2489 duration *
2490 bytes_per_sample *
2491 channel_count) / 1000;
2492 /*
2493 * To have same PCM samples for all channels, the buffer size requires to
2494 * be multiple of (number of channels * bytes per sample)
2495 * For writes to succeed, the buffer must be written at address which is multiple of 32
2496 */
2497 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2498
2499 return (size/(channel_count * bytes_per_sample));
2500}
2501
Ashish Jain5106d362016-05-11 19:23:33 +05302502static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2503{
2504 uint64_t actual_frames_rendered = 0;
2505 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2506
2507 /* This adjustment accounts for buffering after app processor.
2508 * It is based on estimated DSP latency per use case, rather than exact.
2509 */
2510 int64_t platform_latency = platform_render_latency(out->usecase) *
2511 out->sample_rate / 1000000LL;
2512
2513 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2514 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2515 * hence only estimate.
2516 */
2517 int64_t signed_frames = out->written - kernel_buffer_size;
2518
2519 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2520
2521 if (signed_frames > 0)
2522 actual_frames_rendered = signed_frames;
2523
2524 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2525 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2526 (long long int)out->written, (int)kernel_buffer_size,
2527 audio_bytes_per_sample(out->compr_config.codec->format),
2528 popcount(out->channel_mask));
2529
2530 return actual_frames_rendered;
2531}
2532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2534{
2535 struct stream_out *out = (struct stream_out *)stream;
2536
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002537 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538}
2539
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002540static int out_set_sample_rate(struct audio_stream *stream __unused,
2541 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542{
2543 return -ENOSYS;
2544}
2545
2546static size_t out_get_buffer_size(const struct audio_stream *stream)
2547{
2548 struct stream_out *out = (struct stream_out *)stream;
2549
Dhananjay Kumarac341582017-02-23 23:42:25 +05302550 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002552 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2553 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302554 else if (is_offload_usecase(out->usecase) &&
2555 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302556 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002557
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002558 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002559 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560}
2561
2562static uint32_t out_get_channels(const struct audio_stream *stream)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565
2566 return out->channel_mask;
2567}
2568
2569static audio_format_t out_get_format(const struct audio_stream *stream)
2570{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002571 struct stream_out *out = (struct stream_out *)stream;
2572
2573 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574}
2575
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002576static int out_set_format(struct audio_stream *stream __unused,
2577 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578{
2579 return -ENOSYS;
2580}
2581
2582static int out_standby(struct audio_stream *stream)
2583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002586
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302587 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2588 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002590 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002592 if (adev->adm_deregister_stream)
2593 adev->adm_deregister_stream(adev->adm_data, out->handle);
2594
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002595 if (is_offload_usecase(out->usecase))
2596 stop_compressed_output_l(out);
2597
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002598 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002600 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2601 voice_extn_compress_voip_close_output_stream(stream);
2602 pthread_mutex_unlock(&adev->lock);
2603 pthread_mutex_unlock(&out->lock);
2604 ALOGD("VOIP output entered standby");
2605 return 0;
2606 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 if (out->pcm) {
2608 pcm_close(out->pcm);
2609 out->pcm = NULL;
2610 }
2611 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002612 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302613 out->send_next_track_params = false;
2614 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002615 out->gapless_mdata.encoder_delay = 0;
2616 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 if (out->compr != NULL) {
2618 compress_close(out->compr);
2619 out->compr = NULL;
2620 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002623 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 }
2625 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302626 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 return 0;
2628}
2629
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002630static int out_dump(const struct audio_stream *stream __unused,
2631 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632{
2633 return 0;
2634}
2635
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002636static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2637{
2638 int ret = 0;
2639 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002640
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002641 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002642 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002643 return -EINVAL;
2644 }
2645
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302646 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002647
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002648 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2649 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302650 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002651 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002652 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2653 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302654 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002655 }
2656
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002657 ALOGV("%s new encoder delay %u and padding %u", __func__,
2658 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2659
2660 return 0;
2661}
2662
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002663static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2664{
2665 return out == adev->primary_output || out == adev->voice_tx_output;
2666}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2669{
2670 struct stream_out *out = (struct stream_out *)stream;
2671 struct audio_device *adev = out->dev;
2672 struct str_parms *parms;
2673 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002674 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675
sangwoobc677242013-08-08 16:53:43 +09002676 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002677 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302679 if (!parms)
2680 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002681 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2682 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002684 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002685 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002687 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002688 * When HDMI cable is unplugged the music playback is paused and
2689 * the policy manager sends routing=0. But the audioflinger continues
2690 * to write data until standby time (3sec). As the HDMI core is
2691 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002692 * Avoid this by routing audio to speaker until standby.
2693 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002694 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2695 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302696 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002697 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2698 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002699 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302700 /*
2701 * When A2DP is disconnected the
2702 * music playback is paused and the policy manager sends routing=0
2703 * But the audioflingercontinues to write data until standby time
2704 * (3sec). As BT is turned off, the write gets blocked.
2705 * Avoid this by routing audio to speaker until standby.
2706 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002707 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302708 (val == AUDIO_DEVICE_NONE)) {
2709 val = AUDIO_DEVICE_OUT_SPEAKER;
2710 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302711 /* To avoid a2dp to sco overlapping / BT device improper state
2712 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302713 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302714 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2715 if (!audio_extn_a2dp_is_ready()) {
2716 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2717 //combo usecase just by pass a2dp
2718 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2719 val = AUDIO_DEVICE_OUT_SPEAKER;
2720 } else {
2721 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2722 /* update device to a2dp and don't route as BT returned error
2723 * However it is still possible a2dp routing called because
2724 * of current active device disconnection (like wired headset)
2725 */
2726 out->devices = val;
2727 pthread_mutex_unlock(&out->lock);
2728 pthread_mutex_unlock(&adev->lock);
2729 goto error;
2730 }
2731 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302732 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 /*
2734 * select_devices() call below switches all the usecases on the same
2735 * backend to the new device. Refer to check_usecases_codec_backend() in
2736 * the select_devices(). But how do we undo this?
2737 *
2738 * For example, music playback is active on headset (deep-buffer usecase)
2739 * and if we go to ringtones and select a ringtone, low-latency usecase
2740 * will be started on headset+speaker. As we can't enable headset+speaker
2741 * and headset devices at the same time, select_devices() switches the music
2742 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2743 * So when the ringtone playback is completed, how do we undo the same?
2744 *
2745 * We are relying on the out_set_parameters() call on deep-buffer output,
2746 * once the ringtone playback is ended.
2747 * NOTE: We should not check if the current devices are same as new devices.
2748 * Because select_devices() must be called to switch back the music
2749 * playback to headset.
2750 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002751 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002752 audio_devices_t new_dev = val;
2753 bool same_dev = out->devices == new_dev;
2754 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002755
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002756 if (output_drives_call(adev, out)) {
2757 if(!voice_is_in_call(adev)) {
2758 if (adev->mode == AUDIO_MODE_IN_CALL) {
2759 adev->current_call_output = out;
2760 ret = voice_start_call(adev);
2761 }
2762 } else {
2763 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002764 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002765 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002766 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002767
2768 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002769 if (!same_dev) {
2770 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302771 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2772 adev->perf_lock_opts,
2773 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002774 if (adev->adm_on_routing_change)
2775 adev->adm_on_routing_change(adev->adm_data,
2776 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002777 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002778 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302779 if (!same_dev)
2780 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002781 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002782 }
2783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002785 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002787
2788 if (out == adev->primary_output) {
2789 pthread_mutex_lock(&adev->lock);
2790 audio_extn_set_parameters(adev, parms);
2791 pthread_mutex_unlock(&adev->lock);
2792 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002793 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002794 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002795 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002796
2797 audio_extn_dts_create_state_notifier_node(out->usecase);
2798 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2799 popcount(out->channel_mask),
2800 out->playback_started);
2801
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002802 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002803 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002804
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302805 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2806 if (err >= 0) {
2807 strlcpy(out->profile, value, sizeof(out->profile));
2808 ALOGV("updating stream profile with value '%s'", out->profile);
2809 lock_output_stream(out);
2810 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2811 &adev->streams_output_cfg_list,
2812 out->devices, out->flags, out->format,
2813 out->sample_rate, out->bit_width,
2814 out->channel_mask, out->profile,
2815 &out->app_type_cfg);
2816 pthread_mutex_unlock(&out->lock);
2817 }
2818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302820error:
Eric Laurent994a6932013-07-17 11:51:42 -07002821 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 return ret;
2823}
2824
2825static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2826{
2827 struct stream_out *out = (struct stream_out *)stream;
2828 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002829 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 char value[256];
2831 struct str_parms *reply = str_parms_create();
2832 size_t i, j;
2833 int ret;
2834 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002835
2836 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002837 if (reply) {
2838 str_parms_destroy(reply);
2839 }
2840 if (query) {
2841 str_parms_destroy(query);
2842 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002843 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2844 return NULL;
2845 }
2846
Eric Laurent994a6932013-07-17 11:51:42 -07002847 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2849 if (ret >= 0) {
2850 value[0] = '\0';
2851 i = 0;
2852 while (out->supported_channel_masks[i] != 0) {
2853 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2854 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2855 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002856 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002858 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859 first = false;
2860 break;
2861 }
2862 }
2863 i++;
2864 }
2865 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2866 str = str_parms_to_str(reply);
2867 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002868 voice_extn_out_get_parameters(out, query, reply);
2869 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002870 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002871 free(str);
2872 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002875
Alexy Joseph62142aa2015-11-16 15:10:34 -08002876
2877 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2878 if (ret >= 0) {
2879 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302880 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2881 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002882 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302883 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002884 } else {
2885 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302886 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002887 }
2888 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002889 if (str)
2890 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002891 str = str_parms_to_str(reply);
2892 }
2893
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002894 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2895 if (ret >= 0) {
2896 value[0] = '\0';
2897 i = 0;
2898 first = true;
2899 while (out->supported_formats[i] != 0) {
2900 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2901 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2902 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002903 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002904 }
2905 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2906 first = false;
2907 break;
2908 }
2909 }
2910 i++;
2911 }
2912 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002913 if (str)
2914 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002915 str = str_parms_to_str(reply);
2916 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002917
2918 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2919 if (ret >= 0) {
2920 value[0] = '\0';
2921 i = 0;
2922 first = true;
2923 while (out->supported_sample_rates[i] != 0) {
2924 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2925 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2926 if (!first) {
2927 strlcat(value, "|", sizeof(value));
2928 }
2929 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2930 first = false;
2931 break;
2932 }
2933 }
2934 i++;
2935 }
2936 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2937 if (str)
2938 free(str);
2939 str = str_parms_to_str(reply);
2940 }
2941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 str_parms_destroy(query);
2943 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002944 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 return str;
2946}
2947
2948static uint32_t out_get_latency(const struct audio_stream_out *stream)
2949{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002950 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002952 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953
Alexy Josephaa54c872014-12-03 02:46:47 -08002954 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002955 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002956 } else if (out->realtime) {
2957 // since the buffer won't be filled up faster than realtime,
2958 // return a smaller number
2959 if (out->config.rate)
2960 period_ms = (out->af_period_multiplier * out->config.period_size *
2961 1000) / (out->config.rate);
2962 else
2963 period_ms = 0;
2964 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002965 } else {
2966 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002968 }
2969
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002970 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2971 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2972 latency += audio_extn_a2dp_get_encoder_latency();
2973
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302974 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002975 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976}
2977
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302978static float AmpToDb(float amplification)
2979{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302980 float db = DSD_VOLUME_MIN_DB;
2981 if (amplification > 0) {
2982 db = 20 * log10(amplification);
2983 if(db < DSD_VOLUME_MIN_DB)
2984 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302985 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302986 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302987}
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989static int out_set_volume(struct audio_stream_out *stream, float left,
2990 float right)
2991{
Eric Laurenta9024de2013-04-04 09:19:12 -07002992 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002993 int volume[2];
2994
Eric Laurenta9024de2013-04-04 09:19:12 -07002995 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2996 /* only take left channel into account: the API is for stereo anyway */
2997 out->muted = (left == 0.0f);
2998 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002999 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303000 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003001 /*
3002 * Set mute or umute on HDMI passthrough stream.
3003 * Only take left channel into account.
3004 * Mute is 0 and unmute 1
3005 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303006 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303007 } else if (out->format == AUDIO_FORMAT_DSD){
3008 char mixer_ctl_name[128] = "DSD Volume";
3009 struct audio_device *adev = out->dev;
3010 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3011
3012 if (!ctl) {
3013 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3014 __func__, mixer_ctl_name);
3015 return -EINVAL;
3016 }
3017 volume[0] = (int)(AmpToDb(left));
3018 volume[1] = (int)(AmpToDb(right));
3019 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3020 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003021 } else {
3022 char mixer_ctl_name[128];
3023 struct audio_device *adev = out->dev;
3024 struct mixer_ctl *ctl;
3025 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003026 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003028 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3029 "Compress Playback %d Volume", pcm_device_id);
3030 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3031 if (!ctl) {
3032 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3033 __func__, mixer_ctl_name);
3034 return -EINVAL;
3035 }
3036 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3037 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3038 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3039 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003041 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 return -ENOSYS;
3044}
3045
3046static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3047 size_t bytes)
3048{
3049 struct stream_out *out = (struct stream_out *)stream;
3050 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303051 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003052 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003054 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303055
Naresh Tanniru80659832014-06-04 18:17:56 +05303056 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003057
Dhananjay Kumarac341582017-02-23 23:42:25 +05303058 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303059 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303060 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3061 pthread_mutex_unlock(&out->lock);
3062 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303063 } else {
3064 /* increase written size during SSR to avoid mismatch
3065 * with the written frames count in AF
3066 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003067 // bytes per frame
3068 size_t bpf = audio_bytes_per_sample(out->format) *
3069 audio_channel_count_from_out_mask(out->channel_mask);
3070 if (bpf != 0)
3071 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303072 ALOGD(" %s: sound card is not active/SSR state", __func__);
3073 ret= -EIO;
3074 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303075 }
3076 }
3077
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303078 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303079 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3080 if (audio_bytes_per_sample(out->format) != 0)
3081 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3082 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303083 goto exit;
3084 }
3085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003087 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003088 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003089 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3090 ret = voice_extn_compress_voip_start_output_stream(out);
3091 else
3092 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003093 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003096 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 goto exit;
3098 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003099
3100 if (last_known_cal_step != -1) {
3101 ALOGD("%s: retry previous failed cal level set", __func__);
3102 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105
Ashish Jain81eb2a82015-05-13 10:52:34 +05303106 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003107 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303108 adev->is_channel_status_set = true;
3109 }
3110
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003111 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003112 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003113 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003114 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003115 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3116 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303117 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3118 ALOGD("copl(%p):send next track params in gapless", out);
3119 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3120 out->send_next_track_params = false;
3121 out->is_compr_metadata_avail = false;
3122 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003123 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303124 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303125 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003126
Ashish Jain83a6cc22016-06-28 14:34:17 +05303127 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303128 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303129 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303130 pthread_mutex_unlock(&out->lock);
3131 return -EINVAL;
3132 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303133 audio_format_t dst_format = out->hal_op_format;
3134 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303135
3136 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3137 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3138
Ashish Jain83a6cc22016-06-28 14:34:17 +05303139 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303140 dst_format,
3141 buffer,
3142 src_format,
3143 frames);
3144
Ashish Jain83a6cc22016-06-28 14:34:17 +05303145 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303146 bytes_to_write);
3147
3148 /*Convert written bytes in audio flinger format*/
3149 if (ret > 0)
3150 ret = ((ret * format_to_bitwidth_table[out->format]) /
3151 format_to_bitwidth_table[dst_format]);
3152 }
3153 } else
3154 ret = compress_write(out->compr, buffer, bytes);
3155
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303156 if (ret < 0)
3157 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303158 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303159 /*msg to cb thread only if non blocking write is enabled*/
3160 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303161 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003162 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303163 } else if (-ENETRESET == ret) {
3164 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3165 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3166 pthread_mutex_unlock(&out->lock);
3167 out_standby(&out->stream.common);
3168 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 }
Ashish Jain5106d362016-05-11 19:23:33 +05303170 if ( ret == (ssize_t)bytes && !out->non_blocking)
3171 out->written += bytes;
3172
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303173 /* Call compr start only when non-zero bytes of data is there to be rendered */
3174 if (!out->playback_started && ret > 0) {
3175 int status = compress_start(out->compr);
3176 if (status < 0) {
3177 ret = status;
3178 ALOGE("%s: compr start failed with err %d", __func__, errno);
3179 goto exit;
3180 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003181 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182 out->playback_started = 1;
3183 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003184
3185 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3186 popcount(out->channel_mask),
3187 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003188 }
3189 pthread_mutex_unlock(&out->lock);
3190 return ret;
3191 } else {
3192 if (out->pcm) {
3193 if (out->muted)
3194 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003195
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303196 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003197
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003198 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003199
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003200 if (out->config.rate)
3201 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3202 out->config.rate;
3203
3204 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3205
3206 request_out_focus(out, ns);
3207
3208 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003209 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003210 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303211 out->convert_buffer != NULL) {
3212
3213 memcpy_by_audio_format(out->convert_buffer,
3214 out->hal_op_format,
3215 buffer,
3216 out->hal_ip_format,
3217 out->config.period_size * out->config.channels);
3218
3219 ret = pcm_write(out->pcm, out->convert_buffer,
3220 (out->config.period_size *
3221 out->config.channels *
3222 format_to_bitwidth_table[out->hal_op_format]));
3223 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003224 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303225 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003226
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003227 release_out_focus(out);
3228
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303229 if (ret < 0)
3230 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303231 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3232 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3233 else
3234 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 }
3237
3238exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303239 /* ToDo: There may be a corner case when SSR happens back to back during
3240 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303241 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303242 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303243 }
3244
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 pthread_mutex_unlock(&out->lock);
3246
3247 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003248 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003249 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303250 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303251 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303252 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303253 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303254 out->standby = true;
3255 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303257 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3258 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3259 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 }
3261 return bytes;
3262}
3263
3264static int out_get_render_position(const struct audio_stream_out *stream,
3265 uint32_t *dsp_frames)
3266{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303268 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003269
3270 if (dsp_frames == NULL)
3271 return -EINVAL;
3272
3273 *dsp_frames = 0;
3274 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003275 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303276
3277 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3278 * this operation and adev_close_output_stream(where out gets reset).
3279 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303280 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303281 *dsp_frames = get_actual_pcm_frames_rendered(out);
3282 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3283 return 0;
3284 }
3285
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003286 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303287 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303288 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303290 if (ret < 0)
3291 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303293 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 }
3295 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303296 if (-ENETRESET == ret) {
3297 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3298 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3299 return -EINVAL;
3300 } else if(ret < 0) {
3301 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3302 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303303 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3304 /*
3305 * Handle corner case where compress session is closed during SSR
3306 * and timestamp is queried
3307 */
3308 ALOGE(" ERROR: sound card not active, return error");
3309 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303310 } else {
3311 return 0;
3312 }
Zhou Song32a556e2015-05-05 10:46:56 +08003313 } else if (audio_is_linear_pcm(out->format)) {
3314 *dsp_frames = out->written;
3315 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003316 } else
3317 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318}
3319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003320static int out_add_audio_effect(const struct audio_stream *stream __unused,
3321 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return 0;
3324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3327 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return 0;
3330}
3331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003332static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3333 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334{
3335 return -EINVAL;
3336}
3337
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003338static int out_get_presentation_position(const struct audio_stream_out *stream,
3339 uint64_t *frames, struct timespec *timestamp)
3340{
3341 struct stream_out *out = (struct stream_out *)stream;
3342 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003343 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003344
Ashish Jain5106d362016-05-11 19:23:33 +05303345 /* below piece of code is not guarded against any lock because audioFliner serializes
3346 * this operation and adev_close_output_stream( where out gets reset).
3347 */
3348 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303349 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303350 *frames = get_actual_pcm_frames_rendered(out);
3351 /* this is the best we can do */
3352 clock_gettime(CLOCK_MONOTONIC, timestamp);
3353 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3354 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3355 return 0;
3356 }
3357
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003358 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003359
Ashish Jain5106d362016-05-11 19:23:33 +05303360 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3361 ret = compress_get_tstamp(out->compr, &dsp_frames,
3362 &out->sample_rate);
3363 ALOGVV("%s rendered frames %ld sample_rate %d",
3364 __func__, dsp_frames, out->sample_rate);
3365 *frames = dsp_frames;
3366 if (ret < 0)
3367 ret = -errno;
3368 if (-ENETRESET == ret) {
3369 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3370 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3371 ret = -EINVAL;
3372 } else
3373 ret = 0;
3374 /* this is the best we can do */
3375 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003376 } else {
3377 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003378 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003379 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3380 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003381 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003382 // This adjustment accounts for buffering after app processor.
3383 // It is based on estimated DSP latency per use case, rather than exact.
3384 signed_frames -=
3385 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3386
Eric Laurent949a0892013-09-20 09:20:13 -07003387 // It would be unusual for this value to be negative, but check just in case ...
3388 if (signed_frames >= 0) {
3389 *frames = signed_frames;
3390 ret = 0;
3391 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003392 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303393 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3394 *frames = out->written;
3395 clock_gettime(CLOCK_MONOTONIC, timestamp);
3396 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003397 }
3398 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003399 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003400 return ret;
3401}
3402
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003403static int out_set_callback(struct audio_stream_out *stream,
3404 stream_callback_t callback, void *cookie)
3405{
3406 struct stream_out *out = (struct stream_out *)stream;
3407
3408 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003409 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003410 out->offload_callback = callback;
3411 out->offload_cookie = cookie;
3412 pthread_mutex_unlock(&out->lock);
3413 return 0;
3414}
3415
3416static int out_pause(struct audio_stream_out* stream)
3417{
3418 struct stream_out *out = (struct stream_out *)stream;
3419 int status = -ENOSYS;
3420 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003421 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003422 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003423 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303425 struct audio_device *adev = out->dev;
3426 int snd_scard_state = get_snd_card_state(adev);
3427
3428 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3429 status = compress_pause(out->compr);
3430
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003432
Mingming Yin21854652016-04-13 11:54:02 -07003433 if (audio_extn_passthru_is_active()) {
3434 ALOGV("offload use case, pause passthru");
3435 audio_extn_passthru_on_pause(out);
3436 }
3437
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303438 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003439 audio_extn_dts_notify_playback_state(out->usecase, 0,
3440 out->sample_rate, popcount(out->channel_mask),
3441 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003442 }
3443 pthread_mutex_unlock(&out->lock);
3444 }
3445 return status;
3446}
3447
3448static int out_resume(struct audio_stream_out* stream)
3449{
3450 struct stream_out *out = (struct stream_out *)stream;
3451 int status = -ENOSYS;
3452 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003453 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003454 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003455 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003456 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303458 struct audio_device *adev = out->dev;
3459 int snd_scard_state = get_snd_card_state(adev);
3460
Mingming Yin21854652016-04-13 11:54:02 -07003461 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3462 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3463 pthread_mutex_lock(&out->dev->lock);
3464 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003465 pthread_mutex_unlock(&out->dev->lock);
3466 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303467 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003468 }
3469 if (!status) {
3470 out->offload_state = OFFLOAD_STATE_PLAYING;
3471 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303472 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003473 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3474 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003475 }
3476 pthread_mutex_unlock(&out->lock);
3477 }
3478 return status;
3479}
3480
3481static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3482{
3483 struct stream_out *out = (struct stream_out *)stream;
3484 int status = -ENOSYS;
3485 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003486 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003487 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3489 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3490 else
3491 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3492 pthread_mutex_unlock(&out->lock);
3493 }
3494 return status;
3495}
3496
3497static int out_flush(struct audio_stream_out* stream)
3498{
3499 struct stream_out *out = (struct stream_out *)stream;
3500 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003501 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003502 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003503 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003504 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3505 stop_compressed_output_l(out);
3506 out->written = 0;
3507 } else {
3508 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3509 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003511 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 return 0;
3513 }
3514 return -ENOSYS;
3515}
3516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517/** audio_stream_in implementation **/
3518static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3519{
3520 struct stream_in *in = (struct stream_in *)stream;
3521
3522 return in->config.rate;
3523}
3524
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003525static int in_set_sample_rate(struct audio_stream *stream __unused,
3526 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527{
3528 return -ENOSYS;
3529}
3530
3531static size_t in_get_buffer_size(const struct audio_stream *stream)
3532{
3533 struct stream_in *in = (struct stream_in *)stream;
3534
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003535 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3536 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003537 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3538 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303539 else if(audio_extn_cin_attached_usecase(in->usecase))
3540 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003541
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003542 return in->config.period_size * in->af_period_multiplier *
3543 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544}
3545
3546static uint32_t in_get_channels(const struct audio_stream *stream)
3547{
3548 struct stream_in *in = (struct stream_in *)stream;
3549
3550 return in->channel_mask;
3551}
3552
3553static audio_format_t in_get_format(const struct audio_stream *stream)
3554{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003555 struct stream_in *in = (struct stream_in *)stream;
3556
3557 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558}
3559
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003560static int in_set_format(struct audio_stream *stream __unused,
3561 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
3563 return -ENOSYS;
3564}
3565
3566static int in_standby(struct audio_stream *stream)
3567{
3568 struct stream_in *in = (struct stream_in *)stream;
3569 struct audio_device *adev = in->dev;
3570 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303571 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3572 stream, in->usecase, use_case_table[in->usecase]);
3573
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003574 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003575 if (!in->standby && in->is_st_session) {
3576 ALOGD("%s: sound trigger pcm stop lab", __func__);
3577 audio_extn_sound_trigger_stop_lab(in);
3578 in->standby = 1;
3579 }
3580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003582 if (adev->adm_deregister_stream)
3583 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3584
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003585 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003587 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3588 voice_extn_compress_voip_close_input_stream(stream);
3589 ALOGD("VOIP input entered standby");
3590 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303591 if (audio_extn_cin_attached_usecase(in->usecase))
3592 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003593 if (in->pcm) {
3594 pcm_close(in->pcm);
3595 in->pcm = NULL;
3596 }
3597 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003598 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003599 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 }
3601 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003602 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 return status;
3604}
3605
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003606static int in_dump(const struct audio_stream *stream __unused,
3607 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608{
3609 return 0;
3610}
3611
3612static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3613{
3614 struct stream_in *in = (struct stream_in *)stream;
3615 struct audio_device *adev = in->dev;
3616 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003618 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303620 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 parms = str_parms_create_str(kvpairs);
3622
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303623 if (!parms)
3624 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003625 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003626 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003627
3628 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3629 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 val = atoi(value);
3631 /* no audio source uses val == 0 */
3632 if ((in->source != val) && (val != 0)) {
3633 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003634 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3635 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3636 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003637 (in->config.rate == 8000 || in->config.rate == 16000 ||
3638 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003639 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003640 err = voice_extn_compress_voip_open_input_stream(in);
3641 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003642 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003643 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003644 }
3645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 }
3647 }
3648
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003649 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3650 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003652 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 in->device = val;
3654 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003655 if (!in->standby && !in->is_st_session) {
3656 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003657 if (adev->adm_on_routing_change)
3658 adev->adm_on_routing_change(adev->adm_data,
3659 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003660 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 }
3663 }
3664
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303665 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3666 if (err >= 0) {
3667 strlcpy(in->profile, value, sizeof(in->profile));
3668 ALOGV("updating stream profile with value '%s'", in->profile);
3669 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3670 &adev->streams_input_cfg_list,
3671 in->device, in->flags, in->format,
3672 in->sample_rate, in->bit_width,
3673 in->profile, &in->app_type_cfg);
3674 }
3675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003677 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678
3679 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303680error:
Eric Laurent994a6932013-07-17 11:51:42 -07003681 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 return ret;
3683}
3684
3685static char* in_get_parameters(const struct audio_stream *stream,
3686 const char *keys)
3687{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003688 struct stream_in *in = (struct stream_in *)stream;
3689 struct str_parms *query = str_parms_create_str(keys);
3690 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003691 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003692
3693 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003694 if (reply) {
3695 str_parms_destroy(reply);
3696 }
3697 if (query) {
3698 str_parms_destroy(query);
3699 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003700 ALOGE("in_get_parameters: failed to create query or reply");
3701 return NULL;
3702 }
3703
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003704 ALOGV("%s: enter: keys - %s", __func__, keys);
3705
3706 voice_extn_in_get_parameters(in, query, reply);
3707
3708 str = str_parms_to_str(reply);
3709 str_parms_destroy(query);
3710 str_parms_destroy(reply);
3711
3712 ALOGV("%s: exit: returns - %s", __func__, str);
3713 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714}
3715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003716static int in_set_gain(struct audio_stream_in *stream __unused,
3717 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718{
3719 return 0;
3720}
3721
3722static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3723 size_t bytes)
3724{
3725 struct stream_in *in = (struct stream_in *)stream;
3726 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303727 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303728 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303729 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003731 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303732
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003733 if (in->is_st_session) {
3734 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3735 /* Read from sound trigger HAL */
3736 audio_extn_sound_trigger_read(in, buffer, bytes);
3737 pthread_mutex_unlock(&in->lock);
3738 return bytes;
3739 }
3740
Ashish Jainbbce4322016-02-16 13:25:27 +05303741 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003742 ALOGD(" %s: sound card is not active/SSR state", __func__);
3743 ret= -EIO;;
3744 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303745 }
3746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003748 pthread_mutex_lock(&adev->lock);
3749 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3750 ret = voice_extn_compress_voip_start_input_stream(in);
3751 else
3752 ret = start_input_stream(in);
3753 pthread_mutex_unlock(&adev->lock);
3754 if (ret != 0) {
3755 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 }
3757 in->standby = 0;
3758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003760 // what's the duration requested by the client?
3761 long ns = 0;
3762
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303763 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003764 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3765 in->config.rate;
3766
3767 request_in_focus(in, ns);
3768 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003769
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303770 if (audio_extn_cin_attached_usecase(in->usecase)) {
3771 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3772 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303773 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003774 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303775 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003776 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003777 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003778 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303779 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003780 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303781 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3782 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3783 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3784 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303785 ret = -EINVAL;
3786 goto exit;
3787 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303788 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303789 ret = -errno;
3790 }
3791 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303792 /* bytes read is always set to bytes for non compress usecases */
3793 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 }
3795
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003796 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 /*
3799 * Instead of writing zeroes here, we could trust the hardware
3800 * to always provide zeroes when muted.
3801 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303802 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3803 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 memset(buffer, 0, bytes);
3805
3806exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303807 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303808 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003809 if (-ENETRESET == ret)
3810 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 pthread_mutex_unlock(&in->lock);
3813
3814 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303815 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303816 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303817 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303818 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303819 in->standby = true;
3820 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303821 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3822 bytes_read = bytes;
3823 memset(buffer, 0, bytes);
3824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003826 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303827 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303828 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303830 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831}
3832
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003833static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834{
3835 return 0;
3836}
3837
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003838static int add_remove_audio_effect(const struct audio_stream *stream,
3839 effect_handle_t effect,
3840 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003842 struct stream_in *in = (struct stream_in *)stream;
3843 int status = 0;
3844 effect_descriptor_t desc;
3845
3846 status = (*effect)->get_descriptor(effect, &desc);
3847 if (status != 0)
3848 return status;
3849
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003850 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003851 pthread_mutex_lock(&in->dev->lock);
3852 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3853 in->enable_aec != enable &&
3854 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3855 in->enable_aec = enable;
3856 if (!in->standby)
3857 select_devices(in->dev, in->usecase);
3858 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003859 if (in->enable_ns != enable &&
3860 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3861 in->enable_ns = enable;
3862 if (!in->standby)
3863 select_devices(in->dev, in->usecase);
3864 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003865 pthread_mutex_unlock(&in->dev->lock);
3866 pthread_mutex_unlock(&in->lock);
3867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 return 0;
3869}
3870
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003871static int in_add_audio_effect(const struct audio_stream *stream,
3872 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873{
Eric Laurent994a6932013-07-17 11:51:42 -07003874 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003875 return add_remove_audio_effect(stream, effect, true);
3876}
3877
3878static int in_remove_audio_effect(const struct audio_stream *stream,
3879 effect_handle_t effect)
3880{
Eric Laurent994a6932013-07-17 11:51:42 -07003881 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003882 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883}
3884
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303885int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 audio_io_handle_t handle,
3887 audio_devices_t devices,
3888 audio_output_flags_t flags,
3889 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003890 struct audio_stream_out **stream_out,
3891 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892{
3893 struct audio_device *adev = (struct audio_device *)dev;
3894 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303895 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003896 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303899
3900 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3901 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003902 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303903 return -EINVAL;
3904 }
3905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3907
Mingming Yin3a941d42016-02-17 18:08:05 -08003908 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3909 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303910 devices, flags, &out->stream);
3911
3912
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003913 if (!out) {
3914 return -ENOMEM;
3915 }
3916
Haynes Mathew George204045b2015-02-25 20:32:03 -08003917 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003918 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003919 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 if (devices == AUDIO_DEVICE_NONE)
3922 devices = AUDIO_DEVICE_OUT_SPEAKER;
3923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924 out->flags = flags;
3925 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003926 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003927 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003928 out->sample_rate = config->sample_rate;
3929 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3930 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003931 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003932 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003933 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303934 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935
Mingming Yin3a941d42016-02-17 18:08:05 -08003936 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3937 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3938 pthread_mutex_lock(&adev->lock);
3939 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3940 ret = read_hdmi_sink_caps(out);
3941 pthread_mutex_unlock(&adev->lock);
3942 if (ret != 0) {
3943 if (ret == -ENOSYS) {
3944 /* ignore and go with default */
3945 ret = 0;
3946 } else {
3947 ALOGE("error reading hdmi sink caps");
3948 goto error_open;
3949 }
3950 }
3951 }
3952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303954 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003955 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003956 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003957 ret = voice_extn_compress_voip_open_output_stream(out);
3958 if (ret != 0) {
3959 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3960 __func__, ret);
3961 goto error_open;
3962 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003963 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05303964 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003966 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3967 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3968 ALOGE("%s: Unsupported Offload information", __func__);
3969 ret = -EINVAL;
3970 goto error_open;
3971 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003972
Mingming Yin3a941d42016-02-17 18:08:05 -08003973 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003974 if(config->offload_info.format == 0)
3975 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003976 if (config->offload_info.sample_rate == 0)
3977 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003978 }
3979
Mingming Yin90310102013-11-13 16:57:00 -08003980 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303981 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003982 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 ret = -EINVAL;
3984 goto error_open;
3985 }
3986
3987 out->compr_config.codec = (struct snd_codec *)
3988 calloc(1, sizeof(struct snd_codec));
3989
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003990 if (!out->compr_config.codec) {
3991 ret = -ENOMEM;
3992 goto error_open;
3993 }
3994
Dhananjay Kumarac341582017-02-23 23:42:25 +05303995 out->stream.pause = out_pause;
3996 out->stream.resume = out_resume;
3997 out->stream.flush = out_flush;
3998 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07003999 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004000 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304001 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004002 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304003 } else {
4004 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4005 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004006 }
vivek mehta446c3962015-09-14 10:57:35 -07004007
4008 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004009 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4010 config->format == 0 && config->sample_rate == 0 &&
4011 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004012 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004013 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4014 } else {
4015 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4016 ret = -EEXIST;
4017 goto error_open;
4018 }
vivek mehta446c3962015-09-14 10:57:35 -07004019 }
4020
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004021 if (config->offload_info.channel_mask)
4022 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004023 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004024 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004025 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004026 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304027 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004028 ret = -EINVAL;
4029 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004030 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004031
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004032 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004033 out->sample_rate = config->offload_info.sample_rate;
4034
Mingming Yin3ee55c62014-08-04 14:23:35 -07004035 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304037 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4038 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4039 audio_extn_dolby_send_ddp_endp_params(adev);
4040 audio_extn_dolby_set_dmid(adev);
4041 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004042
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004043 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004044 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004045 out->compr_config.codec->bit_rate =
4046 config->offload_info.bit_rate;
4047 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304048 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004049 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304050 /* Update bit width only for non passthrough usecases.
4051 * For passthrough usecases, the output will always be opened @16 bit
4052 */
4053 if (!audio_extn_passthru_is_passthrough_stream(out))
4054 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004055 /*TODO: Do we need to change it for passthrough */
4056 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004057
Manish Dewangana6fc5442015-08-24 20:30:31 +05304058 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4059 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304060 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304061 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304062 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4063 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304064
4065 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4066 AUDIO_FORMAT_PCM) {
4067
4068 /*Based on platform support, configure appropriate alsa format for corresponding
4069 *hal input format.
4070 */
4071 out->compr_config.codec->format = hal_format_to_alsa(
4072 config->offload_info.format);
4073
Ashish Jain83a6cc22016-06-28 14:34:17 +05304074 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304075 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304076 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304077
Dhananjay Kumarac341582017-02-23 23:42:25 +05304078 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304079 *hal input format and alsa format might differ based on platform support.
4080 */
4081 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304082 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304083
4084 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4085
4086 /* Check if alsa session is configured with the same format as HAL input format,
4087 * if not then derive correct fragment size needed to accomodate the
4088 * conversion of HAL input format to alsa format.
4089 */
4090 audio_extn_utils_update_direct_pcm_fragment_size(out);
4091
4092 /*if hal input and output fragment size is different this indicates HAL input format is
4093 *not same as the alsa format
4094 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304095 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304096 /*Allocate a buffer to convert input data to the alsa configured format.
4097 *size of convert buffer is equal to the size required to hold one fragment size
4098 *worth of pcm data, this is because flinger does not write more than fragment_size
4099 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304100 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4101 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304102 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4103 ret = -ENOMEM;
4104 goto error_open;
4105 }
4106 }
4107 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4108 out->compr_config.fragment_size =
4109 audio_extn_passthru_get_buffer_size(&config->offload_info);
4110 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4111 } else {
4112 out->compr_config.fragment_size =
4113 platform_get_compress_offload_buffer_size(&config->offload_info);
4114 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4115 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004116
Amit Shekhar6f461b12014-08-01 14:52:58 -07004117 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304118 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004119
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304120 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4121 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4122 }
4123
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004124 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4125 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004126
Alexy Josephaa54c872014-12-03 02:46:47 -08004127
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004128 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304129 out->send_next_track_params = false;
4130 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004131 out->offload_state = OFFLOAD_STATE_IDLE;
4132 out->playback_started = 0;
4133
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004134 audio_extn_dts_create_state_notifier_node(out->usecase);
4135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004136 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4137 __func__, config->offload_info.version,
4138 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304139
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304140 /* Check if DSD audio format is supported in codec
4141 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304142 */
4143
4144 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304145 (!platform_check_codec_dsd_support(adev->platform) ||
4146 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304147 ret = -EINVAL;
4148 goto error_open;
4149 }
4150
Ashish Jain5106d362016-05-11 19:23:33 +05304151 /* Disable gapless if any of the following is true
4152 * passthrough playback
4153 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304154 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304155 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304156 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304157 (config->format == AUDIO_FORMAT_DSD) ||
4158 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304159 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304160 check_and_set_gapless_mode(adev, false);
4161 } else
4162 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004163
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304164 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004165 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4166 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304167 if (config->format == AUDIO_FORMAT_DSD) {
4168 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4169 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4170 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004171
4172 create_offload_callback_thread(out);
4173
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004174 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304175 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004176 if (ret != 0) {
4177 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4178 __func__, ret);
4179 goto error_open;
4180 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004181 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4182 if (config->sample_rate == 0)
4183 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4184 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4185 config->sample_rate != 8000) {
4186 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4187 ret = -EINVAL;
4188 goto error_open;
4189 }
4190 out->sample_rate = config->sample_rate;
4191 out->config.rate = config->sample_rate;
4192 if (config->format == AUDIO_FORMAT_DEFAULT)
4193 config->format = AUDIO_FORMAT_PCM_16_BIT;
4194 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4195 config->format = AUDIO_FORMAT_PCM_16_BIT;
4196 ret = -EINVAL;
4197 goto error_open;
4198 }
4199 out->format = config->format;
4200 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4201 out->config = pcm_config_afe_proxy_playback;
4202 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004203 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304204 unsigned int channels = 0;
4205 /*Update config params to default if not set by the caller*/
4206 if (config->sample_rate == 0)
4207 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4208 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4209 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4210 if (config->format == AUDIO_FORMAT_DEFAULT)
4211 config->format = AUDIO_FORMAT_PCM_16_BIT;
4212
4213 channels = audio_channel_count_from_out_mask(out->channel_mask);
4214
Ashish Jain83a6cc22016-06-28 14:34:17 +05304215 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4216 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004217 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4218 out->flags);
4219 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304220 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4221 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4222 out->config = pcm_config_low_latency;
4223 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4224 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4225 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304226 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4227 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4228 if (out->config.period_size <= 0) {
4229 ALOGE("Invalid configuration period size is not valid");
4230 ret = -EINVAL;
4231 goto error_open;
4232 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304233 } else {
4234 /* primary path is the default path selected if no other outputs are available/suitable */
4235 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4236 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4237 }
4238 out->hal_ip_format = format = out->format;
4239 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4240 out->hal_op_format = pcm_format_to_hal(out->config.format);
4241 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4242 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004243 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304244 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304245 if (out->hal_ip_format != out->hal_op_format) {
4246 uint32_t buffer_size = out->config.period_size *
4247 format_to_bitwidth_table[out->hal_op_format] *
4248 out->config.channels;
4249 out->convert_buffer = calloc(1, buffer_size);
4250 if (out->convert_buffer == NULL){
4251 ALOGE("Allocation failed for convert buffer for size %d",
4252 out->compr_config.fragment_size);
4253 ret = -ENOMEM;
4254 goto error_open;
4255 }
4256 ALOGD("Convert buffer allocated of size %d", buffer_size);
4257 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 }
4259
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004260 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4261 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304262
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004263 /* TODO remove this hardcoding and check why width is zero*/
4264 if (out->bit_width == 0)
4265 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304266 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004267 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304268 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304269 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304270 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004271 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4272 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4273 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004274 if(adev->primary_output == NULL)
4275 adev->primary_output = out;
4276 else {
4277 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004278 ret = -EEXIST;
4279 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004280 }
4281 }
4282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 /* Check if this usecase is already existing */
4284 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004285 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4286 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004288 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004289 ret = -EEXIST;
4290 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293 pthread_mutex_unlock(&adev->lock);
4294
4295 out->stream.common.get_sample_rate = out_get_sample_rate;
4296 out->stream.common.set_sample_rate = out_set_sample_rate;
4297 out->stream.common.get_buffer_size = out_get_buffer_size;
4298 out->stream.common.get_channels = out_get_channels;
4299 out->stream.common.get_format = out_get_format;
4300 out->stream.common.set_format = out_set_format;
4301 out->stream.common.standby = out_standby;
4302 out->stream.common.dump = out_dump;
4303 out->stream.common.set_parameters = out_set_parameters;
4304 out->stream.common.get_parameters = out_get_parameters;
4305 out->stream.common.add_audio_effect = out_add_audio_effect;
4306 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4307 out->stream.get_latency = out_get_latency;
4308 out->stream.set_volume = out_set_volume;
4309 out->stream.write = out_write;
4310 out->stream.get_render_position = out_get_render_position;
4311 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004312 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004314 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004316 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004317 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318
4319 config->format = out->stream.common.get_format(&out->stream.common);
4320 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4321 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4322
4323 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304324 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004325 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004326
4327 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4328 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4329 popcount(out->channel_mask), out->playback_started);
4330
Eric Laurent994a6932013-07-17 11:51:42 -07004331 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004333
4334error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304335 if (out->convert_buffer)
4336 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004337 free(out);
4338 *stream_out = NULL;
4339 ALOGD("%s: exit: ret %d", __func__, ret);
4340 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341}
4342
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304343void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344 struct audio_stream_out *stream)
4345{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004346 struct stream_out *out = (struct stream_out *)stream;
4347 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004348 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004349
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304350 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4351
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004352 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304353 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004354 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304355 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004356 if(ret != 0)
4357 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4358 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004359 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004360 out_standby(&stream->common);
4361
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004362 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004363 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004365 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004366 if (out->compr_config.codec != NULL)
4367 free(out->compr_config.codec);
4368 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004369
Ashish Jain83a6cc22016-06-28 14:34:17 +05304370 if (out->convert_buffer != NULL) {
4371 free(out->convert_buffer);
4372 out->convert_buffer = NULL;
4373 }
4374
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004375 if (adev->voice_tx_output == out)
4376 adev->voice_tx_output = NULL;
4377
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304378 if (adev->primary_output == out)
4379 adev->primary_output = NULL;
4380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004381 pthread_cond_destroy(&out->cond);
4382 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004384 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385}
4386
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004387static void close_compress_sessions(struct audio_device *adev)
4388{
Mingming Yin7b762e72015-03-04 13:47:32 -08004389 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304390 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004391 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004392 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304393
4394 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004395 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304396 if (is_offload_usecase(usecase->id)) {
4397 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004398 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4399 out = usecase->stream.out;
4400 pthread_mutex_unlock(&adev->lock);
4401 out_standby(&out->stream.common);
4402 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004403 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004404 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304405 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004406 }
4407 pthread_mutex_unlock(&adev->lock);
4408}
4409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4411{
4412 struct audio_device *adev = (struct audio_device *)dev;
4413 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004415 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004416 int ret;
4417 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004419 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304422 if (!parms)
4423 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004424 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4425 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304426 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304427 if (strstr(snd_card_status, "OFFLINE")) {
4428 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304429 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004430 //close compress sessions on OFFLINE status
4431 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304432 } else if (strstr(snd_card_status, "ONLINE")) {
4433 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304434 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004435 //send dts hpx license if enabled
4436 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304437 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304438 }
4439
4440 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004441 status = voice_set_parameters(adev, parms);
4442 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004443 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004445 status = platform_set_parameters(adev->platform, parms);
4446 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004447 goto done;
4448
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004449 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4450 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004451 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4453 adev->bluetooth_nrec = true;
4454 else
4455 adev->bluetooth_nrec = false;
4456 }
4457
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004458 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4459 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4461 adev->screen_off = false;
4462 else
4463 adev->screen_off = true;
4464 }
4465
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004466 ret = str_parms_get_int(parms, "rotation", &val);
4467 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004468 bool reverse_speakers = false;
4469 switch(val) {
4470 // FIXME: note that the code below assumes that the speakers are in the correct placement
4471 // relative to the user when the device is rotated 90deg from its default rotation. This
4472 // assumption is device-specific, not platform-specific like this code.
4473 case 270:
4474 reverse_speakers = true;
4475 break;
4476 case 0:
4477 case 90:
4478 case 180:
4479 break;
4480 default:
4481 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004482 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004483 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004484 if (status == 0) {
4485 if (adev->speaker_lr_swap != reverse_speakers) {
4486 adev->speaker_lr_swap = reverse_speakers;
4487 // only update the selected device if there is active pcm playback
4488 struct audio_usecase *usecase;
4489 struct listnode *node;
4490 list_for_each(node, &adev->usecase_list) {
4491 usecase = node_to_item(node, struct audio_usecase, list);
4492 if (usecase->type == PCM_PLAYBACK) {
4493 select_devices(adev, usecase->id);
4494 break;
4495 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004496 }
4497 }
4498 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004499 }
4500
Mingming Yin514a8bc2014-07-29 15:22:21 -07004501 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4502 if (ret >= 0) {
4503 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4504 adev->bt_wb_speech_enabled = true;
4505 else
4506 adev->bt_wb_speech_enabled = false;
4507 }
4508
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004509 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4510 if (ret >= 0) {
4511 val = atoi(value);
4512 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004513 ALOGV("cache new ext disp type and edid");
4514 ret = platform_get_ext_disp_type(adev->platform);
4515 if (ret < 0) {
4516 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004517 status = ret;
4518 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004519 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004520 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004521 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004522 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004523 /*
4524 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4525 * Per AudioPolicyManager, USB device is higher priority than WFD.
4526 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4527 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4528 * starting voice call on USB
4529 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004530 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4531 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004532 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4533 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004534 }
vivek mehta344576a2016-04-12 18:56:03 -07004535 ALOGV("detected USB connect .. disable proxy");
4536 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004537 }
4538 }
4539
4540 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4541 if (ret >= 0) {
4542 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004543 /*
4544 * The HDMI / Displayport disconnect handling has been moved to
4545 * audio extension to ensure that its parameters are not
4546 * invalidated prior to updating sysfs of the disconnect event
4547 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4548 */
4549 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004550 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004551 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4552 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304553 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4554 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004555 }
vivek mehta344576a2016-04-12 18:56:03 -07004556 ALOGV("detected USB disconnect .. enable proxy");
4557 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004558 }
4559 }
4560
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304561 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4562 if (ret >= 0) {
4563 struct audio_usecase *usecase;
4564 struct listnode *node;
4565 list_for_each(node, &adev->usecase_list) {
4566 usecase = node_to_item(node, struct audio_usecase, list);
4567 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004568 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304569 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304570 lock_output_stream(usecase->stream.out);
4571 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304572 //force device switch to re configure encoder
4573 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304574 audio_extn_a2dp_set_handoff_mode(false);
4575 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304576 break;
4577 }
4578 }
4579 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004580
4581 //handle vr audio setparam
4582 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4583 value, sizeof(value));
4584 if (ret >= 0) {
4585 ALOGI("Setting vr mode to be %s", value);
4586 if (!strncmp(value, "true", 4)) {
4587 adev->vr_audio_mode_enabled = true;
4588 ALOGI("Setting vr mode to true");
4589 } else if (!strncmp(value, "false", 5)) {
4590 adev->vr_audio_mode_enabled = false;
4591 ALOGI("Setting vr mode to false");
4592 } else {
4593 ALOGI("wrong vr mode set");
4594 }
4595 }
4596
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304597 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004598done:
4599 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004600 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304601error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004602 ALOGV("%s: exit with code(%d)", __func__, status);
4603 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604}
4605
4606static char* adev_get_parameters(const struct audio_hw_device *dev,
4607 const char *keys)
4608{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004609 struct audio_device *adev = (struct audio_device *)dev;
4610 struct str_parms *reply = str_parms_create();
4611 struct str_parms *query = str_parms_create_str(keys);
4612 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304613 char value[256] = {0};
4614 int ret = 0;
4615
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004616 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004617 if (reply) {
4618 str_parms_destroy(reply);
4619 }
4620 if (query) {
4621 str_parms_destroy(query);
4622 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004623 ALOGE("adev_get_parameters: failed to create query or reply");
4624 return NULL;
4625 }
4626
Naresh Tannirud7205b62014-06-20 02:54:48 +05304627 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4628 sizeof(value));
4629 if (ret >=0) {
4630 int val = 1;
4631 pthread_mutex_lock(&adev->snd_card_status.lock);
4632 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4633 val = 0;
4634 pthread_mutex_unlock(&adev->snd_card_status.lock);
4635 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4636 goto exit;
4637 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004638 //handle vr audio getparam
4639
4640 ret = str_parms_get_str(query,
4641 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4642 value, sizeof(value));
4643
4644 if (ret >= 0) {
4645 bool vr_audio_enabled = false;
4646 pthread_mutex_lock(&adev->lock);
4647 vr_audio_enabled = adev->vr_audio_mode_enabled;
4648 pthread_mutex_unlock(&adev->lock);
4649
4650 ALOGI("getting vr mode to %d", vr_audio_enabled);
4651
4652 if (vr_audio_enabled) {
4653 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4654 "true");
4655 goto exit;
4656 } else {
4657 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4658 "false");
4659 goto exit;
4660 }
4661 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004662
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004663 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004664 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004665 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004666 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304667 pthread_mutex_unlock(&adev->lock);
4668
Naresh Tannirud7205b62014-06-20 02:54:48 +05304669exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004670 str = str_parms_to_str(reply);
4671 str_parms_destroy(query);
4672 str_parms_destroy(reply);
4673
4674 ALOGV("%s: exit: returns - %s", __func__, str);
4675 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676}
4677
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004678static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679{
4680 return 0;
4681}
4682
4683static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4684{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004685 int ret;
4686 struct audio_device *adev = (struct audio_device *)dev;
4687 pthread_mutex_lock(&adev->lock);
4688 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004689 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004690 pthread_mutex_unlock(&adev->lock);
4691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692}
4693
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004694static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4695 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696{
4697 return -ENOSYS;
4698}
4699
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004700static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4701 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702{
4703 return -ENOSYS;
4704}
4705
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004706static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4707 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708{
4709 return -ENOSYS;
4710}
4711
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004712static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4713 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714{
4715 return -ENOSYS;
4716}
4717
4718static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4719{
4720 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722 pthread_mutex_lock(&adev->lock);
4723 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004724 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004726 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004727 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004728 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004729 adev->current_call_output = NULL;
4730 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731 }
4732 pthread_mutex_unlock(&adev->lock);
4733 return 0;
4734}
4735
4736static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4737{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004738 int ret;
4739
4740 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004741 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004742 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4743 pthread_mutex_unlock(&adev->lock);
4744
4745 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746}
4747
4748static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4749{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004750 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004751 return 0;
4752}
4753
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004754static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004755 const struct audio_config *config)
4756{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004757 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004759 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4760 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761}
4762
4763static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004764 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 audio_devices_t devices,
4766 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004767 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304768 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004769 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004770 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771{
4772 struct audio_device *adev = (struct audio_device *)dev;
4773 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004774 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004775 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004776 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304777 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004779 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304780 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4781 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004782 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784
4785 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004786
4787 if (!in) {
4788 ALOGE("failed to allocate input stream");
4789 return -ENOMEM;
4790 }
4791
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304792 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304793 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4794 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004795 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004796 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 in->stream.common.get_sample_rate = in_get_sample_rate;
4799 in->stream.common.set_sample_rate = in_set_sample_rate;
4800 in->stream.common.get_buffer_size = in_get_buffer_size;
4801 in->stream.common.get_channels = in_get_channels;
4802 in->stream.common.get_format = in_get_format;
4803 in->stream.common.set_format = in_set_format;
4804 in->stream.common.standby = in_standby;
4805 in->stream.common.dump = in_dump;
4806 in->stream.common.set_parameters = in_set_parameters;
4807 in->stream.common.get_parameters = in_get_parameters;
4808 in->stream.common.add_audio_effect = in_add_audio_effect;
4809 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4810 in->stream.set_gain = in_set_gain;
4811 in->stream.read = in_read;
4812 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4813
4814 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004815 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 in->standby = 1;
4818 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004819 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004820 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304822 in->usecase = USECASE_AUDIO_RECORD;
4823 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4824 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4825 is_low_latency = true;
4826#if LOW_LATENCY_CAPTURE_USE_CASE
4827 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4828#endif
4829 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4830 }
4831
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004832 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004833 if (in->realtime) {
4834 in->config = pcm_config_audio_capture_rt;
4835 in->sample_rate = in->config.rate;
4836 in->af_period_multiplier = af_period_multiplier;
4837 } else {
4838 in->config = pcm_config_audio_capture;
4839 in->config.rate = config->sample_rate;
4840 in->sample_rate = config->sample_rate;
4841 in->af_period_multiplier = 1;
4842 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304843 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304845 /* restrict 24 bit capture for unprocessed source only
4846 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4847 */
4848 if (config->format == AUDIO_FORMAT_DEFAULT) {
4849 config->format = AUDIO_FORMAT_PCM_16_BIT;
4850 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4851 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4852 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4853 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4854 bool ret_error = false;
4855 in->bit_width = 24;
4856 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4857 from HAL is 24_packed and 8_24
4858 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4859 24_packed return error indicating supported format is 24_packed
4860 *> In case of any other source requesting 24 bit or float return error
4861 indicating format supported is 16 bit only.
4862
4863 on error flinger will retry with supported format passed
4864 */
4865 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4866 (source != AUDIO_SOURCE_CAMCORDER)) {
4867 config->format = AUDIO_FORMAT_PCM_16_BIT;
4868 if (config->sample_rate > 48000)
4869 config->sample_rate = 48000;
4870 ret_error = true;
4871 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4872 in->config.format = PCM_FORMAT_S24_3LE;
4873 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4874 in->config.format = PCM_FORMAT_S24_LE;
4875 } else {
4876 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4877 ret_error = true;
4878 }
4879
4880 if (ret_error) {
4881 ret = -EINVAL;
4882 goto err_open;
4883 }
4884 }
4885
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304886 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304887 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4888 (adev->mode != AUDIO_MODE_IN_CALL)) {
4889 ret = -EINVAL;
4890 goto err_open;
4891 }
4892
4893 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4894 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004895 if (config->sample_rate == 0)
4896 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4897 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4898 config->sample_rate != 8000) {
4899 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4900 ret = -EINVAL;
4901 goto err_open;
4902 }
4903 if (config->format == AUDIO_FORMAT_DEFAULT)
4904 config->format = AUDIO_FORMAT_PCM_16_BIT;
4905 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4906 config->format = AUDIO_FORMAT_PCM_16_BIT;
4907 ret = -EINVAL;
4908 goto err_open;
4909 }
4910
4911 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4912 in->config = pcm_config_afe_proxy_record;
4913 in->config.channels = channel_count;
4914 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304915 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304916 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4917 in, config, &channel_mask_updated)) {
4918 if (channel_mask_updated == true) {
4919 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4920 __func__, config->channel_mask);
4921 ret = -EINVAL;
4922 goto err_open;
4923 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304924 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004925 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004926 audio_extn_compr_cap_format_supported(config->format) &&
4927 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004928 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304929 } else if (audio_extn_cin_applicable_stream(in)) {
4930 ret = audio_extn_cin_configure_input_stream(in);
4931 if (ret)
4932 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004933 } else {
4934 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004935 if (!in->realtime) {
4936 in->format = config->format;
4937 frame_size = audio_stream_in_frame_size(&in->stream);
4938 buffer_size = get_input_buffer_size(config->sample_rate,
4939 config->format,
4940 channel_count,
4941 is_low_latency);
4942 in->config.period_size = buffer_size / frame_size;
4943 }
4944
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004945 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004946 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004947 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004948 (in->config.rate == 8000 || in->config.rate == 16000 ||
4949 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004950 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4951 voice_extn_compress_voip_open_input_stream(in);
4952 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004953 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004954
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304955 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4956 &adev->streams_input_cfg_list,
4957 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304958 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304959
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004960 /* This stream could be for sound trigger lab,
4961 get sound trigger pcm if present */
4962 audio_extn_sound_trigger_check_and_get_session(in);
4963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004964 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004965 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004966 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967
4968err_open:
4969 free(in);
4970 *stream_in = NULL;
4971 return ret;
4972}
4973
4974static void adev_close_input_stream(struct audio_hw_device *dev,
4975 struct audio_stream_in *stream)
4976{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004977 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004978 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004979 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304980
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304981 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004982
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304983 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004984 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304985
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004986 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304987 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004988 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304989 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004990 if (ret != 0)
4991 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4992 __func__, ret);
4993 } else
4994 in_standby(&stream->common);
4995
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004996 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004997 audio_extn_ssr_deinit();
4998 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004999
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305000 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005001 audio_extn_compr_cap_format_supported(in->config.format))
5002 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305003
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305004 if (audio_extn_cin_attached_usecase(in->usecase))
5005 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005006
Mingming Yinfd7607b2016-01-22 12:48:44 -08005007 if (in->is_st_session) {
5008 ALOGV("%s: sound trigger pcm stop lab", __func__);
5009 audio_extn_sound_trigger_stop_lab(in);
5010 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005011 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012 return;
5013}
5014
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005015static int adev_dump(const audio_hw_device_t *device __unused,
5016 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017{
5018 return 0;
5019}
5020
5021static int adev_close(hw_device_t *device)
5022{
5023 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005024
5025 if (!adev)
5026 return 0;
5027
5028 pthread_mutex_lock(&adev_init_lock);
5029
5030 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005031 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005032 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305033 audio_extn_utils_release_streams_cfg_lists(
5034 &adev->streams_output_cfg_list,
5035 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305036 if (audio_extn_qaf_is_enabled())
5037 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005038 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005039 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005040 free(adev->snd_dev_ref_cnt);
5041 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005042 if (adev->adm_deinit)
5043 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305044 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005045 free(device);
5046 adev = NULL;
5047 }
5048 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050 return 0;
5051}
5052
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005053/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5054 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5055 * just that it _might_ work.
5056 */
5057static int period_size_is_plausible_for_low_latency(int period_size)
5058{
5059 switch (period_size) {
5060 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005061 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005062 case 240:
5063 case 320:
5064 case 480:
5065 return 1;
5066 default:
5067 return 0;
5068 }
5069}
5070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005071static int adev_open(const hw_module_t *module, const char *name,
5072 hw_device_t **device)
5073{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305074 int ret;
5075
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005076 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005077 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5078
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005079 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005080 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005081 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005082 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005083 ALOGD("%s: returning existing instance of adev", __func__);
5084 ALOGD("%s: exit", __func__);
5085 pthread_mutex_unlock(&adev_init_lock);
5086 return 0;
5087 }
5088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005089 adev = calloc(1, sizeof(struct audio_device));
5090
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005091 if (!adev) {
5092 pthread_mutex_unlock(&adev_init_lock);
5093 return -ENOMEM;
5094 }
5095
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005096 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5099 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5100 adev->device.common.module = (struct hw_module_t *)module;
5101 adev->device.common.close = adev_close;
5102
5103 adev->device.init_check = adev_init_check;
5104 adev->device.set_voice_volume = adev_set_voice_volume;
5105 adev->device.set_master_volume = adev_set_master_volume;
5106 adev->device.get_master_volume = adev_get_master_volume;
5107 adev->device.set_master_mute = adev_set_master_mute;
5108 adev->device.get_master_mute = adev_get_master_mute;
5109 adev->device.set_mode = adev_set_mode;
5110 adev->device.set_mic_mute = adev_set_mic_mute;
5111 adev->device.get_mic_mute = adev_get_mic_mute;
5112 adev->device.set_parameters = adev_set_parameters;
5113 adev->device.get_parameters = adev_get_parameters;
5114 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5115 adev->device.open_output_stream = adev_open_output_stream;
5116 adev->device.close_output_stream = adev_close_output_stream;
5117 adev->device.open_input_stream = adev_open_input_stream;
5118 adev->device.close_input_stream = adev_close_input_stream;
5119 adev->device.dump = adev_dump;
5120
5121 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005122 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005123 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005124 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005125 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005127 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005128 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005129 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005130 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005131 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005132 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005133 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005134 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305135 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305136 adev->perf_lock_opts[0] = 0x101;
5137 adev->perf_lock_opts[1] = 0x20E;
5138 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305139
5140 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5141 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005143 adev->platform = platform_init(adev);
5144 if (!adev->platform) {
5145 free(adev->snd_dev_ref_cnt);
5146 free(adev);
5147 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5148 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005149 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305150 pthread_mutex_destroy(&adev->lock);
5151 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005152 return -EINVAL;
5153 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005154
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305155 if (audio_extn_qaf_is_enabled()) {
5156 ret = audio_extn_qaf_init(adev);
5157 if (ret < 0) {
5158 free(adev);
5159 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5160 *device = NULL;
5161 pthread_mutex_unlock(&adev_init_lock);
5162 pthread_mutex_destroy(&adev->lock);
5163 return ret;
5164 }
5165
5166 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5167 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5168 }
5169
Naresh Tanniru4c630392014-05-12 01:05:52 +05305170 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5171
Eric Laurentc4aef752013-09-12 17:45:53 -07005172 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5173 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5174 if (adev->visualizer_lib == NULL) {
5175 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5176 } else {
5177 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5178 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005179 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005180 "visualizer_hal_start_output");
5181 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005182 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005183 "visualizer_hal_stop_output");
5184 }
5185 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305186 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005187 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005188 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005189 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005190
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005191 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5192 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5193 if (adev->offload_effects_lib == NULL) {
5194 ALOGE("%s: DLOPEN failed for %s", __func__,
5195 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5196 } else {
5197 ALOGV("%s: DLOPEN successful for %s", __func__,
5198 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5199 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305200 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005201 "offload_effects_bundle_hal_start_output");
5202 adev->offload_effects_stop_output =
5203 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5204 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005205 adev->offload_effects_set_hpx_state =
5206 (int (*)(bool))dlsym(adev->offload_effects_lib,
5207 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305208 adev->offload_effects_get_parameters =
5209 (void (*)(struct str_parms *, struct str_parms *))
5210 dlsym(adev->offload_effects_lib,
5211 "offload_effects_bundle_get_parameters");
5212 adev->offload_effects_set_parameters =
5213 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5214 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005215 }
5216 }
5217
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005218 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5219 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5220 if (adev->adm_lib == NULL) {
5221 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5222 } else {
5223 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5224 adev->adm_init = (adm_init_t)
5225 dlsym(adev->adm_lib, "adm_init");
5226 adev->adm_deinit = (adm_deinit_t)
5227 dlsym(adev->adm_lib, "adm_deinit");
5228 adev->adm_register_input_stream = (adm_register_input_stream_t)
5229 dlsym(adev->adm_lib, "adm_register_input_stream");
5230 adev->adm_register_output_stream = (adm_register_output_stream_t)
5231 dlsym(adev->adm_lib, "adm_register_output_stream");
5232 adev->adm_deregister_stream = (adm_deregister_stream_t)
5233 dlsym(adev->adm_lib, "adm_deregister_stream");
5234 adev->adm_request_focus = (adm_request_focus_t)
5235 dlsym(adev->adm_lib, "adm_request_focus");
5236 adev->adm_abandon_focus = (adm_abandon_focus_t)
5237 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005238 adev->adm_set_config = (adm_set_config_t)
5239 dlsym(adev->adm_lib, "adm_set_config");
5240 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5241 dlsym(adev->adm_lib, "adm_request_focus_v2");
5242 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5243 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5244 adev->adm_on_routing_change = (adm_on_routing_change_t)
5245 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005246 }
5247 }
5248
Mingming Yin514a8bc2014-07-29 15:22:21 -07005249 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005250 //initialize this to false for now,
5251 //this will be set to true through set param
5252 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005253
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005254 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255 *device = &adev->device.common;
5256
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305257 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5258 &adev->streams_output_cfg_list,
5259 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005260
Kiran Kandi910e1862013-10-29 13:29:42 -07005261 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005262
5263 char value[PROPERTY_VALUE_MAX];
5264 int trial;
5265 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5266 trial = atoi(value);
5267 if (period_size_is_plausible_for_low_latency(trial)) {
5268 pcm_config_low_latency.period_size = trial;
5269 pcm_config_low_latency.start_threshold = trial / 4;
5270 pcm_config_low_latency.avail_min = trial / 4;
5271 configured_low_latency_capture_period_size = trial;
5272 }
5273 }
5274 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5275 trial = atoi(value);
5276 if (period_size_is_plausible_for_low_latency(trial)) {
5277 configured_low_latency_capture_period_size = trial;
5278 }
5279 }
5280
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005281 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5282 af_period_multiplier = atoi(value);
5283 if (af_period_multiplier < 0)
5284 af_period_multiplier = 2;
5285 else if (af_period_multiplier > 4)
5286 af_period_multiplier = 4;
5287
5288 ALOGV("new period_multiplier = %d", af_period_multiplier);
5289 }
5290
vivek mehta446c3962015-09-14 10:57:35 -07005291 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005292 pthread_mutex_unlock(&adev_init_lock);
5293
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005294 if (adev->adm_init)
5295 adev->adm_data = adev->adm_init();
5296
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305297 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305298 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005299 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005300 return 0;
5301}
5302
5303static struct hw_module_methods_t hal_module_methods = {
5304 .open = adev_open,
5305};
5306
5307struct audio_module HAL_MODULE_INFO_SYM = {
5308 .common = {
5309 .tag = HARDWARE_MODULE_TAG,
5310 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5311 .hal_api_version = HARDWARE_HAL_API_VERSION,
5312 .id = AUDIO_HARDWARE_MODULE_ID,
5313 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005314 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315 .methods = &hal_module_methods,
5316 },
5317};