blob: 00adcca0df6da40649c05d09576921040ad88a22 [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));
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301090 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1091 usecase, uc_info, snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001092 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301093 usecase != uc_info &&
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301094 ((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301095 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1096 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301097 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301098 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1099 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1100 ((force_restart_session) ||
1101 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301102
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301103 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1104 __func__, use_case_table[usecase->id],
1105 platform_get_snd_device_name(usecase->out_snd_device));
1106 disable_audio_route(adev, usecase);
1107 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301108 /* Enable existing usecase on derived playback device */
1109 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301110 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 }
1112 }
1113
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301114 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1115 num_uc_to_switch);
1116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001118 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301120 /* Make sure the previous devices to be disabled first and then enable the
1121 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 list_for_each(node, &adev->usecase_list) {
1123 usecase = node_to_item(node, struct audio_usecase, list);
1124 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001125 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 }
1127 }
1128
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001129 list_for_each(node, &adev->usecase_list) {
1130 usecase = node_to_item(node, struct audio_usecase, list);
1131 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301132 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001133 }
1134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 /* Re-route all the usecases on the shared backend other than the
1137 specified usecase to new snd devices */
1138 list_for_each(node, &adev->usecase_list) {
1139 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301140 /* Update the out_snd_device only before enabling the audio route */
1141 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301142 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301143 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301144 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301145 use_case_table[usecase->id],
1146 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001147 /* Update voc calibration before enabling VoIP route */
1148 if (usecase->type == VOIP_CALL)
1149 status = platform_switch_voice_call_device_post(adev->platform,
1150 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001151 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301152 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301153 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 }
1155 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156 }
1157}
1158
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301159static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001160 struct audio_usecase *uc_info,
1161 snd_device_t snd_device)
1162{
1163 struct listnode *node;
1164 struct audio_usecase *usecase;
1165 bool switch_device[AUDIO_USECASE_MAX];
1166 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301167 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001168 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001169
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301170 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1171 snd_device);
1172 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301173
1174 /*
1175 * Make sure out devices is checked against out codec backend device and
1176 * also in devices against in codec backend. Checking out device against in
1177 * codec backend or vice versa causes issues.
1178 */
1179 if (uc_info->type == PCM_CAPTURE)
1180 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 /*
1182 * This function is to make sure that all the active capture usecases
1183 * are always routed to the same input sound device.
1184 * For example, if audio-record and voice-call usecases are currently
1185 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1186 * is received for voice call then we have to make sure that audio-record
1187 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1188 * because of the limitation that two devices cannot be enabled
1189 * at the same time if they share the same backend.
1190 */
1191 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1192 switch_device[i] = false;
1193
1194 list_for_each(node, &adev->usecase_list) {
1195 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301196 /*
1197 * TODO: Enhance below condition to handle BT sco/USB multi recording
1198 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001199 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001200 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301201 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301202 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301203 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001204 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001205 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001206 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1207 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001208 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001209 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 switch_device[usecase->id] = true;
1211 num_uc_to_switch++;
1212 }
1213 }
1214
1215 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001216 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001217
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301218 /* Make sure the previous devices to be disabled first and then enable the
1219 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001220 list_for_each(node, &adev->usecase_list) {
1221 usecase = node_to_item(node, struct audio_usecase, list);
1222 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001223 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001224 }
1225 }
1226
1227 list_for_each(node, &adev->usecase_list) {
1228 usecase = node_to_item(node, struct audio_usecase, list);
1229 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001230 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001231 }
1232 }
1233
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001234 /* Re-route all the usecases on the shared backend other than the
1235 specified usecase to new snd devices */
1236 list_for_each(node, &adev->usecase_list) {
1237 usecase = node_to_item(node, struct audio_usecase, list);
1238 /* Update the in_snd_device only before enabling the audio route */
1239 if (switch_device[usecase->id] ) {
1240 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001241 if (usecase->type != VOICE_CALL) {
1242 /* Update voc calibration before enabling VoIP route */
1243 if (usecase->type == VOIP_CALL)
1244 status = platform_switch_voice_call_device_post(adev->platform,
1245 usecase->out_snd_device,
1246 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301247 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001248 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001249 }
1250 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001251 }
1252}
1253
Mingming Yin3a941d42016-02-17 18:08:05 -08001254static void reset_hdmi_sink_caps(struct stream_out *out) {
1255 int i = 0;
1256
1257 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1258 out->supported_channel_masks[i] = 0;
1259 }
1260 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1261 out->supported_formats[i] = 0;
1262 }
1263 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1264 out->supported_sample_rates[i] = 0;
1265 }
1266}
1267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001269static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270{
Mingming Yin3a941d42016-02-17 18:08:05 -08001271 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001272 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273
Mingming Yin3a941d42016-02-17 18:08:05 -08001274 reset_hdmi_sink_caps(out);
1275
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001276 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001277 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001278 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001279 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001280 }
1281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001284 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001285 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001286 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1287 case 6:
1288 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1291 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1292 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1293 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294 break;
1295 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001296 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001297 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 break;
1299 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001300
1301 // check channel format caps
1302 i = 0;
1303 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1304 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1305 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1306 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1307 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1308 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1309 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1310 }
1311
1312 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1313 ALOGV(":%s HDMI supports DTS format", __func__);
1314 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1315 }
1316
1317 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1318 ALOGV(":%s HDMI supports DTS HD format", __func__);
1319 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1320 }
1321
1322
1323 // check sample rate caps
1324 i = 0;
1325 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1326 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1327 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1328 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1329 }
1330 }
1331
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001332 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333}
1334
Alexy Josephb1379942016-01-29 15:49:38 -08001335audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001336 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001337{
1338 struct audio_usecase *usecase;
1339 struct listnode *node;
1340
1341 list_for_each(node, &adev->usecase_list) {
1342 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001343 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001344 ALOGV("%s: usecase id %d", __func__, usecase->id);
1345 return usecase->id;
1346 }
1347 }
1348 return USECASE_INVALID;
1349}
1350
Alexy Josephb1379942016-01-29 15:49:38 -08001351struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001352 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353{
1354 struct audio_usecase *usecase;
1355 struct listnode *node;
1356
1357 list_for_each(node, &adev->usecase_list) {
1358 usecase = node_to_item(node, struct audio_usecase, list);
1359 if (usecase->id == uc_id)
1360 return usecase;
1361 }
1362 return NULL;
1363}
1364
Dhananjay Kumard4833242016-10-06 22:09:12 +05301365struct stream_in *get_next_active_input(const struct audio_device *adev)
1366{
1367 struct audio_usecase *usecase;
1368 struct listnode *node;
1369
1370 list_for_each_reverse(node, &adev->usecase_list) {
1371 usecase = node_to_item(node, struct audio_usecase, list);
1372 if (usecase->type == PCM_CAPTURE)
1373 return usecase->stream.in;
1374 }
1375 return NULL;
1376}
1377
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301378/*
1379 * is a true native playback active
1380 */
1381bool audio_is_true_native_stream_active(struct audio_device *adev)
1382{
1383 bool active = false;
1384 int i = 0;
1385 struct listnode *node;
1386
1387 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1388 ALOGV("%s:napb: not in true mode or non hdphones device",
1389 __func__);
1390 active = false;
1391 goto exit;
1392 }
1393
1394 list_for_each(node, &adev->usecase_list) {
1395 struct audio_usecase *uc;
1396 uc = node_to_item(node, struct audio_usecase, list);
1397 struct stream_out *curr_out =
1398 (struct stream_out*) uc->stream.out;
1399
1400 if (curr_out && PCM_PLAYBACK == uc->type) {
1401 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1402 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1403 uc->id, curr_out->sample_rate,
1404 curr_out->bit_width,
1405 platform_get_snd_device_name(uc->out_snd_device));
1406
1407 if (is_offload_usecase(uc->id) &&
1408 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1409 active = true;
1410 ALOGD("%s:napb:native stream detected", __func__);
1411 }
1412 }
1413 }
1414exit:
1415 return active;
1416}
1417
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301418/*
1419 * if native DSD playback active
1420 */
1421bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1422{
1423 bool active = false;
1424 struct listnode *node = NULL;
1425 struct audio_usecase *uc = NULL;
1426 struct stream_out *curr_out = NULL;
1427
1428 list_for_each(node, &adev->usecase_list) {
1429 uc = node_to_item(node, struct audio_usecase, list);
1430 curr_out = (struct stream_out*) uc->stream.out;
1431
1432 if (curr_out && PCM_PLAYBACK == uc->type &&
1433 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1434 active = true;
1435 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301436 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301437 }
1438 }
1439 return active;
1440}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301441
1442static bool force_device_switch(struct audio_usecase *usecase)
1443{
1444 bool ret = false;
1445 bool is_it_true_mode = false;
1446
1447 if (is_offload_usecase(usecase->id) &&
1448 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001449 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1450 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1451 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301452 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1453 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1454 (!is_it_true_mode && adev->native_playback_enabled)){
1455 ret = true;
1456 ALOGD("napb: time to toggle native mode");
1457 }
1458 }
1459
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301460 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301461 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1462 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301463 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001464 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301465 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301466 ALOGD("Force a2dp device switch to update new encoder config");
1467 ret = true;
1468 }
1469
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301470 return ret;
1471}
1472
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001473int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001475 snd_device_t out_snd_device = SND_DEVICE_NONE;
1476 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 struct audio_usecase *usecase = NULL;
1478 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001479 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001480 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001481 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301484 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1485
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 usecase = get_usecase_from_list(adev, uc_id);
1487 if (usecase == NULL) {
1488 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1489 return -EINVAL;
1490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001492 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001493 (usecase->type == VOIP_CALL) ||
1494 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301495 if(usecase->stream.out == NULL) {
1496 ALOGE("%s: stream.out is NULL", __func__);
1497 return -EINVAL;
1498 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001499 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001500 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001501 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 usecase->devices = usecase->stream.out->devices;
1503 } else {
1504 /*
1505 * If the voice call is active, use the sound devices of voice call usecase
1506 * so that it would not result any device switch. All the usecases will
1507 * be switched to new device when select_devices() is called for voice call
1508 * usecase. This is to avoid switching devices for voice call when
1509 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001510 * choose voice call device only if the use case device is
1511 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001512 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001513 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001514 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001515 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001516 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1517 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301518 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1519 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001520 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 in_snd_device = vc_usecase->in_snd_device;
1522 out_snd_device = vc_usecase->out_snd_device;
1523 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001524 } else if (voice_extn_compress_voip_is_active(adev)) {
1525 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001526 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001527 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1528 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001529 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001530 in_snd_device = voip_usecase->in_snd_device;
1531 out_snd_device = voip_usecase->out_snd_device;
1532 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001533 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001534 hfp_ucid = audio_extn_hfp_get_usecase();
1535 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001536 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001537 in_snd_device = hfp_usecase->in_snd_device;
1538 out_snd_device = hfp_usecase->out_snd_device;
1539 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540 }
1541 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301542 if (usecase->stream.out == NULL) {
1543 ALOGE("%s: stream.out is NULL", __func__);
1544 return -EINVAL;
1545 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546 usecase->devices = usecase->stream.out->devices;
1547 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001548 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001549 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001550 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001551 if (usecase->stream.out == adev->primary_output &&
1552 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001553 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001554 select_devices(adev, adev->active_input->usecase);
1555 }
1556 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301558 if (usecase->stream.in == NULL) {
1559 ALOGE("%s: stream.in is NULL", __func__);
1560 return -EINVAL;
1561 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562 usecase->devices = usecase->stream.in->device;
1563 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001564 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001565 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001566 if (adev->active_input &&
1567 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301568 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1569 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1570 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001571 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001572 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001573 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1574 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001575 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001576 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001577 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 }
1579 }
1580
1581 if (out_snd_device == usecase->out_snd_device &&
1582 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301583
1584 if (!force_device_switch(usecase))
1585 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 }
1587
sangwoobc677242013-08-08 16:53:43 +09001588 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001589 out_snd_device, platform_get_snd_device_name(out_snd_device),
1590 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 /*
1593 * Limitation: While in call, to do a device switch we need to disable
1594 * and enable both RX and TX devices though one of them is same as current
1595 * device.
1596 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001597 if ((usecase->type == VOICE_CALL) &&
1598 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1599 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001600 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001601 }
1602
1603 if (((usecase->type == VOICE_CALL) ||
1604 (usecase->type == VOIP_CALL)) &&
1605 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1606 /* Disable sidetone only if voice/voip call already exists */
1607 if (voice_is_call_state_active(adev) ||
1608 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001609 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001610
1611 /* Disable aanc only if voice call exists */
1612 if (voice_is_call_state_active(adev))
1613 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001614 }
1615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001616 /* Disable current sound devices */
1617 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001618 disable_audio_route(adev, usecase);
1619 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 }
1621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001623 disable_audio_route(adev, usecase);
1624 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625 }
1626
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001627 /* Applicable only on the targets that has external modem.
1628 * New device information should be sent to modem before enabling
1629 * the devices to reduce in-call device switch time.
1630 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001631 if ((usecase->type == VOICE_CALL) &&
1632 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1633 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001634 status = platform_switch_voice_call_enable_device_config(adev->platform,
1635 out_snd_device,
1636 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001637 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001638
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001639 /* Enable new sound devices */
1640 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001641 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301642 if (platform_check_codec_asrc_support(adev->platform))
1643 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001644 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 }
1646
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001647 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301648 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001649 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001650 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001651
Avinash Vaish71a8b972014-07-24 15:36:33 +05301652 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001653 status = platform_switch_voice_call_device_post(adev->platform,
1654 out_snd_device,
1655 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301656 enable_audio_route_for_voice_usecases(adev, usecase);
1657 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001658
sangwoo170731f2013-06-08 15:36:36 +09001659 usecase->in_snd_device = in_snd_device;
1660 usecase->out_snd_device = out_snd_device;
1661
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301662 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1663 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301664 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001665 if ((24 == usecase->stream.out->bit_width) &&
1666 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1667 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1668 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1669 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1670 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1671 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1672 /*
1673 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1674 * configured device sample rate, if not update the COPP rate to be equal to the
1675 * device sample rate, else open COPP at stream sample rate
1676 */
1677 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1678 usecase->stream.out->sample_rate,
1679 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301680 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1681 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001682 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1683 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1684 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1685 }
1686
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001687 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001688 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001689 audio_extn_gef_notify_device_config(
1690 usecase->stream.out->devices,
1691 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001692 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001693 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001694 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301695 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001696 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001697
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001698 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001699 /* Enable aanc only if voice call exists */
1700 if (voice_is_call_state_active(adev))
1701 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1702
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001703 /* Enable sidetone only if other voice/voip call already exists */
1704 if (voice_is_call_state_active(adev) ||
1705 voice_extn_compress_voip_is_started(adev))
1706 voice_set_sidetone(adev, out_snd_device, true);
1707 }
1708
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001709 /* Applicable only on the targets that has external modem.
1710 * Enable device command should be sent to modem only after
1711 * enabling voice call mixer controls
1712 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001713 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001714 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1715 out_snd_device,
1716 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301717 ALOGD("%s: done",__func__);
1718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719 return status;
1720}
1721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722static int stop_input_stream(struct stream_in *in)
1723{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301724 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725 struct audio_usecase *uc_info;
1726 struct audio_device *adev = in->dev;
1727
Eric Laurent994a6932013-07-17 11:51:42 -07001728 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001729 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730 uc_info = get_usecase_from_list(adev, in->usecase);
1731 if (uc_info == NULL) {
1732 ALOGE("%s: Could not find the usecase (%d) in the list",
1733 __func__, in->usecase);
1734 return -EINVAL;
1735 }
1736
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001737 /* Close in-call recording streams */
1738 voice_check_and_stop_incall_rec_usecase(adev, in);
1739
Eric Laurent150dbfe2013-02-27 14:31:02 -08001740 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001741 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001742
1743 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001744 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001746 list_remove(&uc_info->list);
1747 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001749 adev->active_input = get_next_active_input(adev);
1750
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 return ret;
1753}
1754
1755int start_input_stream(struct stream_in *in)
1756{
1757 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001758 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759 struct audio_usecase *uc_info;
1760 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301761 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762
Mingming Yin2664a5b2015-09-03 10:53:11 -07001763 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1764 if (get_usecase_from_list(adev, usecase) == NULL)
1765 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301766 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1767 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001768
Naresh Tanniru80659832014-06-04 18:17:56 +05301769
1770 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301771 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301772 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301773 goto error_config;
1774 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301775
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001776 /* Check if source matches incall recording usecase criteria */
1777 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1778 if (ret)
1779 goto error_config;
1780 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001781 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1782
1783 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1784 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1785 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001786 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001787 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001788
Eric Laurentb23d5282013-05-14 15:27:20 -07001789 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 if (in->pcm_device_id < 0) {
1791 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1792 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001793 ret = -EINVAL;
1794 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796
1797 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001799
1800 if (!uc_info) {
1801 ret = -ENOMEM;
1802 goto error_config;
1803 }
1804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 uc_info->id = in->usecase;
1806 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001807 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001808 uc_info->devices = in->device;
1809 uc_info->in_snd_device = SND_DEVICE_NONE;
1810 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001812 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301813 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1814 adev->perf_lock_opts,
1815 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301818 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1819 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001820
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301821 if (audio_extn_cin_attached_usecase(in->usecase)) {
1822 ret = audio_extn_cin_start_input_stream(in);
1823 if (ret)
1824 goto error_open;
1825 else
1826 goto done_open;
1827 }
1828
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001829 unsigned int flags = PCM_IN;
1830 unsigned int pcm_open_retry_count = 0;
1831
1832 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1833 flags |= PCM_MMAP | PCM_NOIRQ;
1834 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001835 } else if (in->realtime) {
1836 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001837 }
1838
1839 while (1) {
1840 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1841 flags, &in->config);
1842 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1843 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1844 if (in->pcm != NULL) {
1845 pcm_close(in->pcm);
1846 in->pcm = NULL;
1847 }
1848 if (pcm_open_retry_count-- == 0) {
1849 ret = -EIO;
1850 goto error_open;
1851 }
1852 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1853 continue;
1854 }
1855 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001857
1858 ALOGV("%s: pcm_prepare", __func__);
1859 ret = pcm_prepare(in->pcm);
1860 if (ret < 0) {
1861 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1862 pcm_close(in->pcm);
1863 in->pcm = NULL;
1864 goto error_open;
1865 }
1866
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001867 register_in_stream(in);
1868 if (in->realtime) {
1869 ret = pcm_start(in->pcm);
1870 if (ret < 0)
1871 goto error_open;
1872 }
1873
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301874done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301875 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001876 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001877
Eric Laurentc8400632013-02-14 19:04:54 -08001878 return ret;
1879
1880error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301881 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001883error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301884 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301885 /*
1886 * sleep 50ms to allow sufficient time for kernel
1887 * drivers to recover incases like SSR.
1888 */
1889 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001890 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001891
1892 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893}
1894
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001895void lock_input_stream(struct stream_in *in)
1896{
1897 pthread_mutex_lock(&in->pre_lock);
1898 pthread_mutex_lock(&in->lock);
1899 pthread_mutex_unlock(&in->pre_lock);
1900}
1901
1902void lock_output_stream(struct stream_out *out)
1903{
1904 pthread_mutex_lock(&out->pre_lock);
1905 pthread_mutex_lock(&out->lock);
1906 pthread_mutex_unlock(&out->pre_lock);
1907}
1908
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001909/* must be called with out->lock locked */
1910static int send_offload_cmd_l(struct stream_out* out, int command)
1911{
1912 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1913
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001914 if (!cmd) {
1915 ALOGE("failed to allocate mem for command 0x%x", command);
1916 return -ENOMEM;
1917 }
1918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001919 ALOGVV("%s %d", __func__, command);
1920
1921 cmd->cmd = command;
1922 list_add_tail(&out->offload_cmd_list, &cmd->node);
1923 pthread_cond_signal(&out->offload_cond);
1924 return 0;
1925}
1926
1927/* must be called iwth out->lock locked */
1928static void stop_compressed_output_l(struct stream_out *out)
1929{
1930 out->offload_state = OFFLOAD_STATE_IDLE;
1931 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001932 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001933 if (out->compr != NULL) {
1934 compress_stop(out->compr);
1935 while (out->offload_thread_blocked) {
1936 pthread_cond_wait(&out->cond, &out->lock);
1937 }
1938 }
1939}
1940
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001941bool is_offload_usecase(audio_usecase_t uc_id)
1942{
1943 unsigned int i;
1944 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1945 if (uc_id == offload_usecases[i])
1946 return true;
1947 }
1948 return false;
1949}
1950
Dhananjay Kumarac341582017-02-23 23:42:25 +05301951static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001952{
vivek mehta446c3962015-09-14 10:57:35 -07001953 audio_usecase_t ret_uc = USECASE_INVALID;
1954 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001955 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001956 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301957 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001958 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1959 else
1960 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001961
vivek mehta446c3962015-09-14 10:57:35 -07001962 pthread_mutex_lock(&adev->lock);
1963 if (get_usecase_from_list(adev, ret_uc) != NULL)
1964 ret_uc = USECASE_INVALID;
1965 pthread_mutex_unlock(&adev->lock);
1966
1967 return ret_uc;
1968 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001969
1970 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001971 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1972 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1973 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1974 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001975 break;
1976 }
1977 }
vivek mehta446c3962015-09-14 10:57:35 -07001978
1979 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1980 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001981}
1982
1983static void free_offload_usecase(struct audio_device *adev,
1984 audio_usecase_t uc_id)
1985{
vivek mehta446c3962015-09-14 10:57:35 -07001986 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001987 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001988
1989 if (!adev->multi_offload_enable)
1990 return;
1991
1992 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1993 if (offload_usecases[offload_uc_index] == uc_id) {
1994 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001995 break;
1996 }
1997 }
1998 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1999}
2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002001static void *offload_thread_loop(void *context)
2002{
2003 struct stream_out *out = (struct stream_out *) context;
2004 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002005 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2008 set_sched_policy(0, SP_FOREGROUND);
2009 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2010
2011 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002012 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 for (;;) {
2014 struct offload_cmd *cmd = NULL;
2015 stream_callback_event_t event;
2016 bool send_callback = false;
2017
2018 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2019 __func__, list_empty(&out->offload_cmd_list),
2020 out->offload_state);
2021 if (list_empty(&out->offload_cmd_list)) {
2022 ALOGV("%s SLEEPING", __func__);
2023 pthread_cond_wait(&out->offload_cond, &out->lock);
2024 ALOGV("%s RUNNING", __func__);
2025 continue;
2026 }
2027
2028 item = list_head(&out->offload_cmd_list);
2029 cmd = node_to_item(item, struct offload_cmd, node);
2030 list_remove(item);
2031
2032 ALOGVV("%s STATE %d CMD %d out->compr %p",
2033 __func__, out->offload_state, cmd->cmd, out->compr);
2034
2035 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2036 free(cmd);
2037 break;
2038 }
2039
2040 if (out->compr == NULL) {
2041 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002042 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043 pthread_cond_signal(&out->cond);
2044 continue;
2045 }
2046 out->offload_thread_blocked = true;
2047 pthread_mutex_unlock(&out->lock);
2048 send_callback = false;
2049 switch(cmd->cmd) {
2050 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002051 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002053 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 send_callback = true;
2055 event = STREAM_CBK_EVENT_WRITE_READY;
2056 break;
2057 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002058 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302059 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002060 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302061 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002062 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302063 if (ret < 0)
2064 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302065 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302066 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002067 compress_drain(out->compr);
2068 else
2069 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302070 if (ret != -ENETRESET) {
2071 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302072 pthread_mutex_lock(&out->lock);
2073 out->send_new_metadata = 1;
2074 out->send_next_track_params = true;
2075 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302076 event = STREAM_CBK_EVENT_DRAIN_READY;
2077 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2078 } else
2079 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 break;
2081 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002082 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002084 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085 send_callback = true;
2086 event = STREAM_CBK_EVENT_DRAIN_READY;
2087 break;
2088 default:
2089 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2090 break;
2091 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002092 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 out->offload_thread_blocked = false;
2094 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002095 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002096 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002098 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 free(cmd);
2100 }
2101
2102 pthread_cond_signal(&out->cond);
2103 while (!list_empty(&out->offload_cmd_list)) {
2104 item = list_head(&out->offload_cmd_list);
2105 list_remove(item);
2106 free(node_to_item(item, struct offload_cmd, node));
2107 }
2108 pthread_mutex_unlock(&out->lock);
2109
2110 return NULL;
2111}
2112
2113static int create_offload_callback_thread(struct stream_out *out)
2114{
2115 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2116 list_init(&out->offload_cmd_list);
2117 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2118 offload_thread_loop, out);
2119 return 0;
2120}
2121
2122static int destroy_offload_callback_thread(struct stream_out *out)
2123{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002124 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 stop_compressed_output_l(out);
2126 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2127
2128 pthread_mutex_unlock(&out->lock);
2129 pthread_join(out->offload_thread, (void **) NULL);
2130 pthread_cond_destroy(&out->offload_cond);
2131
2132 return 0;
2133}
2134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135static int stop_output_stream(struct stream_out *out)
2136{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302137 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 struct audio_usecase *uc_info;
2139 struct audio_device *adev = out->dev;
2140
Eric Laurent994a6932013-07-17 11:51:42 -07002141 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002142 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 uc_info = get_usecase_from_list(adev, out->usecase);
2144 if (uc_info == NULL) {
2145 ALOGE("%s: Could not find the usecase (%d) in the list",
2146 __func__, out->usecase);
2147 return -EINVAL;
2148 }
2149
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002150 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302151 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002152 if (adev->visualizer_stop_output != NULL)
2153 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002154
2155 audio_extn_dts_remove_state_notifier_node(out->usecase);
2156
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002157 if (adev->offload_effects_stop_output != NULL)
2158 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2159 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002160
Eric Laurent150dbfe2013-02-27 14:31:02 -08002161 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002162 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002163
2164 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002165 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002167 list_remove(&uc_info->list);
2168 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002170 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302171 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002172 ALOGV("Disable passthrough , reset mixer to pcm");
2173 /* NO_PASSTHROUGH */
2174 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002175 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002176 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2177 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002178
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302179 /* Must be called after removing the usecase from list */
2180 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302181 audio_extn_keep_alive_start();
2182
Eric Laurent994a6932013-07-17 11:51:42 -07002183 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 return ret;
2185}
2186
2187int start_output_stream(struct stream_out *out)
2188{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 struct audio_usecase *uc_info;
2191 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302192 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002193 char mixer_ctl_name[128];
2194 struct mixer_ctl *ctl = NULL;
2195 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002197 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2198 ret = -EINVAL;
2199 goto error_config;
2200 }
2201
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302202 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2203 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2204 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302205
Naresh Tanniru80659832014-06-04 18:17:56 +05302206 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302207 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302208 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302209 goto error_config;
2210 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302211
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302212 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2213 if (!audio_extn_a2dp_is_ready()) {
2214 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2215 //combo usecase just by pass a2dp
2216 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2217 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2218 } else {
2219 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2220 ret = -EAGAIN;
2221 goto error_config;
2222 }
2223 }
2224 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002225 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 if (out->pcm_device_id < 0) {
2227 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2228 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002229 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002230 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 }
2232
2233 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002234
2235 if (!uc_info) {
2236 ret = -ENOMEM;
2237 goto error_config;
2238 }
2239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 uc_info->id = out->usecase;
2241 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002242 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002243 uc_info->devices = out->devices;
2244 uc_info->in_snd_device = SND_DEVICE_NONE;
2245 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002246 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302248 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2249 adev->perf_lock_opts,
2250 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302251
2252 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2253 audio_extn_keep_alive_stop();
2254 if (audio_extn_passthru_is_enabled() &&
2255 audio_extn_passthru_is_passthrough_stream(out)) {
2256 audio_extn_passthru_on_start(out);
2257 audio_extn_passthru_update_stream_configuration(adev, out);
2258 }
2259 }
2260
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002261 select_devices(adev, out->usecase);
2262
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002263 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2264 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002265 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002266 unsigned int flags = PCM_OUT;
2267 unsigned int pcm_open_retry_count = 0;
2268 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2269 flags |= PCM_MMAP | PCM_NOIRQ;
2270 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002271 } else if (out->realtime) {
2272 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002273 } else
2274 flags |= PCM_MONOTONIC;
2275
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002276 if ((adev->vr_audio_mode_enabled) &&
2277 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2278 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2279 "PCM_Dev %d Topology", out->pcm_device_id);
2280 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2281 if (!ctl) {
2282 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2283 __func__, mixer_ctl_name);
2284 } else {
2285 //if success use ULLPP
2286 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2287 __func__, mixer_ctl_name, out->pcm_device_id);
2288 //There is a still a possibility that some sessions
2289 // that request for FAST|RAW when 3D audio is active
2290 //can go through ULLPP. Ideally we expects apps to
2291 //listen to audio focus and stop concurrent playback
2292 //Also, we will look for mode flag (voice_in_communication)
2293 //before enabling the realtime flag.
2294 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2295 }
2296 }
2297
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002298 while (1) {
2299 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2300 flags, &out->config);
2301 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2302 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2303 if (out->pcm != NULL) {
2304 pcm_close(out->pcm);
2305 out->pcm = NULL;
2306 }
2307 if (pcm_open_retry_count-- == 0) {
2308 ret = -EIO;
2309 goto error_open;
2310 }
2311 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2312 continue;
2313 }
2314 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002316
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002317 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2318 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002319
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002320 ALOGV("%s: pcm_prepare", __func__);
2321 if (pcm_is_ready(out->pcm)) {
2322 ret = pcm_prepare(out->pcm);
2323 if (ret < 0) {
2324 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2325 pcm_close(out->pcm);
2326 out->pcm = NULL;
2327 goto error_open;
2328 }
2329 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302330 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2331 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002333 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2334 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002336 out->compr = compress_open(adev->snd_card,
2337 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 COMPRESS_IN, &out->compr_config);
2339 if (out->compr && !is_compress_ready(out->compr)) {
2340 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2341 compress_close(out->compr);
2342 out->compr = NULL;
2343 ret = -EIO;
2344 goto error_open;
2345 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302346 /* compress_open sends params of the track, so reset the flag here */
2347 out->is_compr_metadata_avail = false;
2348
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002349 if (out->offload_callback)
2350 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002351
Fred Oh3f43e742015-03-04 18:42:34 -08002352 /* Since small bufs uses blocking writes, a write will be blocked
2353 for the default max poll time (20s) in the event of an SSR.
2354 Reduce the poll time to observe and deal with SSR faster.
2355 */
Ashish Jain5106d362016-05-11 19:23:33 +05302356 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002357 compress_set_max_poll_wait(out->compr, 1000);
2358 }
2359
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002360 audio_extn_dts_create_state_notifier_node(out->usecase);
2361 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2362 popcount(out->channel_mask),
2363 out->playback_started);
2364
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002365#ifdef DS1_DOLBY_DDP_ENABLED
2366 if (audio_extn_is_dolby_format(out->format))
2367 audio_extn_dolby_send_ddp_endp_params(adev);
2368#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302369 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2370 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002371 if (adev->visualizer_start_output != NULL)
2372 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2373 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302374 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002375 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002376 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002378
2379 if (ret == 0) {
2380 register_out_stream(out);
2381 if (out->realtime) {
2382 ret = pcm_start(out->pcm);
2383 if (ret < 0)
2384 goto error_open;
2385 }
2386 }
2387
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302388 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002389 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002390
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002391 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302393 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002395error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302396 /*
2397 * sleep 50ms to allow sufficient time for kernel
2398 * drivers to recover incases like SSR.
2399 */
2400 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002401 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402}
2403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404static int check_input_parameters(uint32_t sample_rate,
2405 audio_format_t format,
2406 int channel_count)
2407{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002408 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302410 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2411 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2412 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002413 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302414 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002415
2416 switch (channel_count) {
2417 case 1:
2418 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302419 case 3:
2420 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002421 case 6:
2422 break;
2423 default:
2424 ret = -EINVAL;
2425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426
2427 switch (sample_rate) {
2428 case 8000:
2429 case 11025:
2430 case 12000:
2431 case 16000:
2432 case 22050:
2433 case 24000:
2434 case 32000:
2435 case 44100:
2436 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302437 case 96000:
2438 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439 break;
2440 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002441 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 }
2443
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002444 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445}
2446
2447static size_t get_input_buffer_size(uint32_t sample_rate,
2448 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002449 int channel_count,
2450 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451{
2452 size_t size = 0;
2453
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002454 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2455 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002457 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002458 if (is_low_latency)
2459 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302460
2461 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002463 /* make sure the size is multiple of 32 bytes
2464 * At 48 kHz mono 16-bit PCM:
2465 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2466 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2467 */
2468 size += 0x1f;
2469 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002470
2471 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472}
2473
Ashish Jain058165c2016-09-28 23:18:48 +05302474static size_t get_output_period_size(uint32_t sample_rate,
2475 audio_format_t format,
2476 int channel_count,
2477 int duration /*in millisecs*/)
2478{
2479 size_t size = 0;
2480 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2481
2482 if ((duration == 0) || (sample_rate == 0) ||
2483 (bytes_per_sample == 0) || (channel_count == 0)) {
2484 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2485 bytes_per_sample, channel_count);
2486 return -EINVAL;
2487 }
2488
2489 size = (sample_rate *
2490 duration *
2491 bytes_per_sample *
2492 channel_count) / 1000;
2493 /*
2494 * To have same PCM samples for all channels, the buffer size requires to
2495 * be multiple of (number of channels * bytes per sample)
2496 * For writes to succeed, the buffer must be written at address which is multiple of 32
2497 */
2498 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2499
2500 return (size/(channel_count * bytes_per_sample));
2501}
2502
Ashish Jain5106d362016-05-11 19:23:33 +05302503static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2504{
2505 uint64_t actual_frames_rendered = 0;
2506 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2507
2508 /* This adjustment accounts for buffering after app processor.
2509 * It is based on estimated DSP latency per use case, rather than exact.
2510 */
2511 int64_t platform_latency = platform_render_latency(out->usecase) *
2512 out->sample_rate / 1000000LL;
2513
2514 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2515 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2516 * hence only estimate.
2517 */
2518 int64_t signed_frames = out->written - kernel_buffer_size;
2519
2520 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2521
2522 if (signed_frames > 0)
2523 actual_frames_rendered = signed_frames;
2524
2525 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2526 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2527 (long long int)out->written, (int)kernel_buffer_size,
2528 audio_bytes_per_sample(out->compr_config.codec->format),
2529 popcount(out->channel_mask));
2530
2531 return actual_frames_rendered;
2532}
2533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2535{
2536 struct stream_out *out = (struct stream_out *)stream;
2537
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002538 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539}
2540
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002541static int out_set_sample_rate(struct audio_stream *stream __unused,
2542 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543{
2544 return -ENOSYS;
2545}
2546
2547static size_t out_get_buffer_size(const struct audio_stream *stream)
2548{
2549 struct stream_out *out = (struct stream_out *)stream;
2550
Dhananjay Kumarac341582017-02-23 23:42:25 +05302551 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002553 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2554 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302555 else if (is_offload_usecase(out->usecase) &&
2556 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302557 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002558
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002559 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002560 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561}
2562
2563static uint32_t out_get_channels(const struct audio_stream *stream)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566
2567 return out->channel_mask;
2568}
2569
2570static audio_format_t out_get_format(const struct audio_stream *stream)
2571{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 struct stream_out *out = (struct stream_out *)stream;
2573
2574 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575}
2576
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002577static int out_set_format(struct audio_stream *stream __unused,
2578 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579{
2580 return -ENOSYS;
2581}
2582
2583static int out_standby(struct audio_stream *stream)
2584{
2585 struct stream_out *out = (struct stream_out *)stream;
2586 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002587
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302588 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2589 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002591 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002593 if (adev->adm_deregister_stream)
2594 adev->adm_deregister_stream(adev->adm_data, out->handle);
2595
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002596 if (is_offload_usecase(out->usecase))
2597 stop_compressed_output_l(out);
2598
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002599 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002601 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2602 voice_extn_compress_voip_close_output_stream(stream);
2603 pthread_mutex_unlock(&adev->lock);
2604 pthread_mutex_unlock(&out->lock);
2605 ALOGD("VOIP output entered standby");
2606 return 0;
2607 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 if (out->pcm) {
2609 pcm_close(out->pcm);
2610 out->pcm = NULL;
2611 }
2612 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002613 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302614 out->send_next_track_params = false;
2615 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002616 out->gapless_mdata.encoder_delay = 0;
2617 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 if (out->compr != NULL) {
2619 compress_close(out->compr);
2620 out->compr = NULL;
2621 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002622 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002624 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 }
2626 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302627 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 return 0;
2629}
2630
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002631static int out_dump(const struct audio_stream *stream __unused,
2632 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633{
2634 return 0;
2635}
2636
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002637static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2638{
2639 int ret = 0;
2640 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002641
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002642 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002643 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002644 return -EINVAL;
2645 }
2646
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302647 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002648
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002649 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2650 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302651 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002652 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002653 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2654 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302655 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002656 }
2657
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002658 ALOGV("%s new encoder delay %u and padding %u", __func__,
2659 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2660
2661 return 0;
2662}
2663
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002664static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2665{
2666 return out == adev->primary_output || out == adev->voice_tx_output;
2667}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2670{
2671 struct stream_out *out = (struct stream_out *)stream;
2672 struct audio_device *adev = out->dev;
2673 struct str_parms *parms;
2674 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002675 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676
sangwoobc677242013-08-08 16:53:43 +09002677 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002678 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302680 if (!parms)
2681 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002682 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2683 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002685 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002686 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002688 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002689 * When HDMI cable is unplugged the music playback is paused and
2690 * the policy manager sends routing=0. But the audioflinger continues
2691 * to write data until standby time (3sec). As the HDMI core is
2692 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002693 * Avoid this by routing audio to speaker until standby.
2694 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002695 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2696 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302697 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002698 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2699 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002700 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302701 /*
2702 * When A2DP is disconnected the
2703 * music playback is paused and the policy manager sends routing=0
2704 * But the audioflingercontinues to write data until standby time
2705 * (3sec). As BT is turned off, the write gets blocked.
2706 * Avoid this by routing audio to speaker until standby.
2707 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002708 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302709 (val == AUDIO_DEVICE_NONE)) {
2710 val = AUDIO_DEVICE_OUT_SPEAKER;
2711 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302712 /* To avoid a2dp to sco overlapping / BT device improper state
2713 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302714 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302715 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2716 if (!audio_extn_a2dp_is_ready()) {
2717 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2718 //combo usecase just by pass a2dp
2719 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2720 val = AUDIO_DEVICE_OUT_SPEAKER;
2721 } else {
2722 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2723 /* update device to a2dp and don't route as BT returned error
2724 * However it is still possible a2dp routing called because
2725 * of current active device disconnection (like wired headset)
2726 */
2727 out->devices = val;
2728 pthread_mutex_unlock(&out->lock);
2729 pthread_mutex_unlock(&adev->lock);
2730 goto error;
2731 }
2732 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302733 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002734 /*
2735 * select_devices() call below switches all the usecases on the same
2736 * backend to the new device. Refer to check_usecases_codec_backend() in
2737 * the select_devices(). But how do we undo this?
2738 *
2739 * For example, music playback is active on headset (deep-buffer usecase)
2740 * and if we go to ringtones and select a ringtone, low-latency usecase
2741 * will be started on headset+speaker. As we can't enable headset+speaker
2742 * and headset devices at the same time, select_devices() switches the music
2743 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2744 * So when the ringtone playback is completed, how do we undo the same?
2745 *
2746 * We are relying on the out_set_parameters() call on deep-buffer output,
2747 * once the ringtone playback is ended.
2748 * NOTE: We should not check if the current devices are same as new devices.
2749 * Because select_devices() must be called to switch back the music
2750 * playback to headset.
2751 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002752 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002753 audio_devices_t new_dev = val;
2754 bool same_dev = out->devices == new_dev;
2755 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002756
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002757 if (output_drives_call(adev, out)) {
2758 if(!voice_is_in_call(adev)) {
2759 if (adev->mode == AUDIO_MODE_IN_CALL) {
2760 adev->current_call_output = out;
2761 ret = voice_start_call(adev);
2762 }
2763 } else {
2764 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002765 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002766 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002767 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002768
2769 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002770 if (!same_dev) {
2771 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302772 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2773 adev->perf_lock_opts,
2774 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002775 if (adev->adm_on_routing_change)
2776 adev->adm_on_routing_change(adev->adm_data,
2777 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002778 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002779 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302780 if (!same_dev)
2781 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002782 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002783 }
2784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002786 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002788
2789 if (out == adev->primary_output) {
2790 pthread_mutex_lock(&adev->lock);
2791 audio_extn_set_parameters(adev, parms);
2792 pthread_mutex_unlock(&adev->lock);
2793 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002794 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002795 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002796 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002797
2798 audio_extn_dts_create_state_notifier_node(out->usecase);
2799 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2800 popcount(out->channel_mask),
2801 out->playback_started);
2802
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002803 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002804 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002805
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302806 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2807 if (err >= 0) {
2808 strlcpy(out->profile, value, sizeof(out->profile));
2809 ALOGV("updating stream profile with value '%s'", out->profile);
2810 lock_output_stream(out);
2811 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2812 &adev->streams_output_cfg_list,
2813 out->devices, out->flags, out->format,
2814 out->sample_rate, out->bit_width,
2815 out->channel_mask, out->profile,
2816 &out->app_type_cfg);
2817 pthread_mutex_unlock(&out->lock);
2818 }
2819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302821error:
Eric Laurent994a6932013-07-17 11:51:42 -07002822 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 return ret;
2824}
2825
2826static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2827{
2828 struct stream_out *out = (struct stream_out *)stream;
2829 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002830 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 char value[256];
2832 struct str_parms *reply = str_parms_create();
2833 size_t i, j;
2834 int ret;
2835 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002836
2837 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002838 if (reply) {
2839 str_parms_destroy(reply);
2840 }
2841 if (query) {
2842 str_parms_destroy(query);
2843 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002844 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2845 return NULL;
2846 }
2847
Eric Laurent994a6932013-07-17 11:51:42 -07002848 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2850 if (ret >= 0) {
2851 value[0] = '\0';
2852 i = 0;
2853 while (out->supported_channel_masks[i] != 0) {
2854 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2855 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2856 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002857 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002859 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 first = false;
2861 break;
2862 }
2863 }
2864 i++;
2865 }
2866 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2867 str = str_parms_to_str(reply);
2868 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002869 voice_extn_out_get_parameters(out, query, reply);
2870 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002871 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002872 free(str);
2873 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002876
Alexy Joseph62142aa2015-11-16 15:10:34 -08002877
2878 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2879 if (ret >= 0) {
2880 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302881 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2882 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002883 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302884 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002885 } else {
2886 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302887 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002888 }
2889 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002890 if (str)
2891 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002892 str = str_parms_to_str(reply);
2893 }
2894
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002895 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2896 if (ret >= 0) {
2897 value[0] = '\0';
2898 i = 0;
2899 first = true;
2900 while (out->supported_formats[i] != 0) {
2901 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2902 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2903 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002904 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002905 }
2906 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2907 first = false;
2908 break;
2909 }
2910 }
2911 i++;
2912 }
2913 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002914 if (str)
2915 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002916 str = str_parms_to_str(reply);
2917 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002918
2919 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2920 if (ret >= 0) {
2921 value[0] = '\0';
2922 i = 0;
2923 first = true;
2924 while (out->supported_sample_rates[i] != 0) {
2925 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2926 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2927 if (!first) {
2928 strlcat(value, "|", sizeof(value));
2929 }
2930 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2931 first = false;
2932 break;
2933 }
2934 }
2935 i++;
2936 }
2937 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2938 if (str)
2939 free(str);
2940 str = str_parms_to_str(reply);
2941 }
2942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 str_parms_destroy(query);
2944 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002945 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 return str;
2947}
2948
2949static uint32_t out_get_latency(const struct audio_stream_out *stream)
2950{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002951 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002953 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954
Alexy Josephaa54c872014-12-03 02:46:47 -08002955 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002956 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002957 } else if (out->realtime) {
2958 // since the buffer won't be filled up faster than realtime,
2959 // return a smaller number
2960 if (out->config.rate)
2961 period_ms = (out->af_period_multiplier * out->config.period_size *
2962 1000) / (out->config.rate);
2963 else
2964 period_ms = 0;
2965 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002966 } else {
2967 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002968 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002969 }
2970
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002971 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2972 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2973 latency += audio_extn_a2dp_get_encoder_latency();
2974
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302975 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002976 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977}
2978
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302979static float AmpToDb(float amplification)
2980{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302981 float db = DSD_VOLUME_MIN_DB;
2982 if (amplification > 0) {
2983 db = 20 * log10(amplification);
2984 if(db < DSD_VOLUME_MIN_DB)
2985 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302986 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302987 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302988}
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990static int out_set_volume(struct audio_stream_out *stream, float left,
2991 float right)
2992{
Eric Laurenta9024de2013-04-04 09:19:12 -07002993 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994 int volume[2];
2995
Eric Laurenta9024de2013-04-04 09:19:12 -07002996 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2997 /* only take left channel into account: the API is for stereo anyway */
2998 out->muted = (left == 0.0f);
2999 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003000 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303001 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003002 /*
3003 * Set mute or umute on HDMI passthrough stream.
3004 * Only take left channel into account.
3005 * Mute is 0 and unmute 1
3006 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303007 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303008 } else if (out->format == AUDIO_FORMAT_DSD){
3009 char mixer_ctl_name[128] = "DSD Volume";
3010 struct audio_device *adev = out->dev;
3011 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3012
3013 if (!ctl) {
3014 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3015 __func__, mixer_ctl_name);
3016 return -EINVAL;
3017 }
3018 volume[0] = (int)(AmpToDb(left));
3019 volume[1] = (int)(AmpToDb(right));
3020 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3021 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003022 } else {
3023 char mixer_ctl_name[128];
3024 struct audio_device *adev = out->dev;
3025 struct mixer_ctl *ctl;
3026 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003027 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003028
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003029 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3030 "Compress Playback %d Volume", pcm_device_id);
3031 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3032 if (!ctl) {
3033 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3034 __func__, mixer_ctl_name);
3035 return -EINVAL;
3036 }
3037 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3038 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3039 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3040 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003041 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003042 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 return -ENOSYS;
3045}
3046
3047static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3048 size_t bytes)
3049{
3050 struct stream_out *out = (struct stream_out *)stream;
3051 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303052 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003053 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003055 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303056
Naresh Tanniru80659832014-06-04 18:17:56 +05303057 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003058
Dhananjay Kumarac341582017-02-23 23:42:25 +05303059 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303060 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303061 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3062 pthread_mutex_unlock(&out->lock);
3063 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303064 } else {
3065 /* increase written size during SSR to avoid mismatch
3066 * with the written frames count in AF
3067 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003068 // bytes per frame
3069 size_t bpf = audio_bytes_per_sample(out->format) *
3070 audio_channel_count_from_out_mask(out->channel_mask);
3071 if (bpf != 0)
3072 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303073 ALOGD(" %s: sound card is not active/SSR state", __func__);
3074 ret= -EIO;
3075 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303076 }
3077 }
3078
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303079 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303080 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3081 if (audio_bytes_per_sample(out->format) != 0)
3082 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3083 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303084 goto exit;
3085 }
3086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003088 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003089 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003090 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3091 ret = voice_extn_compress_voip_start_output_stream(out);
3092 else
3093 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003094 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003097 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 goto exit;
3099 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003100
3101 if (last_known_cal_step != -1) {
3102 ALOGD("%s: retry previous failed cal level set", __func__);
3103 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106
Ashish Jain81eb2a82015-05-13 10:52:34 +05303107 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003108 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303109 adev->is_channel_status_set = true;
3110 }
3111
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003112 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003113 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003114 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003115 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003116 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3117 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303118 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3119 ALOGD("copl(%p):send next track params in gapless", out);
3120 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3121 out->send_next_track_params = false;
3122 out->is_compr_metadata_avail = false;
3123 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003124 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303125 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303126 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003127
Ashish Jain83a6cc22016-06-28 14:34:17 +05303128 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303129 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303130 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303131 pthread_mutex_unlock(&out->lock);
3132 return -EINVAL;
3133 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303134 audio_format_t dst_format = out->hal_op_format;
3135 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303136
3137 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3138 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3139
Ashish Jain83a6cc22016-06-28 14:34:17 +05303140 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303141 dst_format,
3142 buffer,
3143 src_format,
3144 frames);
3145
Ashish Jain83a6cc22016-06-28 14:34:17 +05303146 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303147 bytes_to_write);
3148
3149 /*Convert written bytes in audio flinger format*/
3150 if (ret > 0)
3151 ret = ((ret * format_to_bitwidth_table[out->format]) /
3152 format_to_bitwidth_table[dst_format]);
3153 }
3154 } else
3155 ret = compress_write(out->compr, buffer, bytes);
3156
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303157 if (ret < 0)
3158 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303159 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303160 /*msg to cb thread only if non blocking write is enabled*/
3161 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303162 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303164 } else if (-ENETRESET == ret) {
3165 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3166 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3167 pthread_mutex_unlock(&out->lock);
3168 out_standby(&out->stream.common);
3169 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 }
Ashish Jain5106d362016-05-11 19:23:33 +05303171 if ( ret == (ssize_t)bytes && !out->non_blocking)
3172 out->written += bytes;
3173
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303174 /* Call compr start only when non-zero bytes of data is there to be rendered */
3175 if (!out->playback_started && ret > 0) {
3176 int status = compress_start(out->compr);
3177 if (status < 0) {
3178 ret = status;
3179 ALOGE("%s: compr start failed with err %d", __func__, errno);
3180 goto exit;
3181 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003182 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003183 out->playback_started = 1;
3184 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003185
3186 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3187 popcount(out->channel_mask),
3188 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003189 }
3190 pthread_mutex_unlock(&out->lock);
3191 return ret;
3192 } else {
3193 if (out->pcm) {
3194 if (out->muted)
3195 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003196
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303197 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003198
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003199 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003200
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003201 if (out->config.rate)
3202 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3203 out->config.rate;
3204
3205 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3206
3207 request_out_focus(out, ns);
3208
3209 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003210 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003211 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303212 out->convert_buffer != NULL) {
3213
3214 memcpy_by_audio_format(out->convert_buffer,
3215 out->hal_op_format,
3216 buffer,
3217 out->hal_ip_format,
3218 out->config.period_size * out->config.channels);
3219
3220 ret = pcm_write(out->pcm, out->convert_buffer,
3221 (out->config.period_size *
3222 out->config.channels *
3223 format_to_bitwidth_table[out->hal_op_format]));
3224 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303226 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003227
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003228 release_out_focus(out);
3229
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303230 if (ret < 0)
3231 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303232 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3233 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3234 else
3235 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 }
3238
3239exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303240 /* ToDo: There may be a corner case when SSR happens back to back during
3241 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303242 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303243 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303244 }
3245
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246 pthread_mutex_unlock(&out->lock);
3247
3248 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003249 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003250 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303251 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303252 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303253 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303254 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303255 out->standby = true;
3256 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303258 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3259 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3260 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 }
3262 return bytes;
3263}
3264
3265static int out_get_render_position(const struct audio_stream_out *stream,
3266 uint32_t *dsp_frames)
3267{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303269 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003270
3271 if (dsp_frames == NULL)
3272 return -EINVAL;
3273
3274 *dsp_frames = 0;
3275 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003276 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303277
3278 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3279 * this operation and adev_close_output_stream(where out gets reset).
3280 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303281 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303282 *dsp_frames = get_actual_pcm_frames_rendered(out);
3283 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3284 return 0;
3285 }
3286
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003287 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303288 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303289 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303291 if (ret < 0)
3292 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003293 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303294 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 }
3296 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303297 if (-ENETRESET == ret) {
3298 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3299 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3300 return -EINVAL;
3301 } else if(ret < 0) {
3302 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3303 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303304 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3305 /*
3306 * Handle corner case where compress session is closed during SSR
3307 * and timestamp is queried
3308 */
3309 ALOGE(" ERROR: sound card not active, return error");
3310 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303311 } else {
3312 return 0;
3313 }
Zhou Song32a556e2015-05-05 10:46:56 +08003314 } else if (audio_is_linear_pcm(out->format)) {
3315 *dsp_frames = out->written;
3316 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003317 } else
3318 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319}
3320
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003321static int out_add_audio_effect(const struct audio_stream *stream __unused,
3322 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323{
3324 return 0;
3325}
3326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003327static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3328 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329{
3330 return 0;
3331}
3332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003333static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3334 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335{
3336 return -EINVAL;
3337}
3338
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003339static int out_get_presentation_position(const struct audio_stream_out *stream,
3340 uint64_t *frames, struct timespec *timestamp)
3341{
3342 struct stream_out *out = (struct stream_out *)stream;
3343 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003344 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003345
Ashish Jain5106d362016-05-11 19:23:33 +05303346 /* below piece of code is not guarded against any lock because audioFliner serializes
3347 * this operation and adev_close_output_stream( where out gets reset).
3348 */
3349 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303350 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303351 *frames = get_actual_pcm_frames_rendered(out);
3352 /* this is the best we can do */
3353 clock_gettime(CLOCK_MONOTONIC, timestamp);
3354 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3355 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3356 return 0;
3357 }
3358
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003359 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003360
Ashish Jain5106d362016-05-11 19:23:33 +05303361 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3362 ret = compress_get_tstamp(out->compr, &dsp_frames,
3363 &out->sample_rate);
3364 ALOGVV("%s rendered frames %ld sample_rate %d",
3365 __func__, dsp_frames, out->sample_rate);
3366 *frames = dsp_frames;
3367 if (ret < 0)
3368 ret = -errno;
3369 if (-ENETRESET == ret) {
3370 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3371 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3372 ret = -EINVAL;
3373 } else
3374 ret = 0;
3375 /* this is the best we can do */
3376 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003377 } else {
3378 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003379 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003380 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3381 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003382 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003383 // This adjustment accounts for buffering after app processor.
3384 // It is based on estimated DSP latency per use case, rather than exact.
3385 signed_frames -=
3386 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3387
Eric Laurent949a0892013-09-20 09:20:13 -07003388 // It would be unusual for this value to be negative, but check just in case ...
3389 if (signed_frames >= 0) {
3390 *frames = signed_frames;
3391 ret = 0;
3392 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003393 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303394 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3395 *frames = out->written;
3396 clock_gettime(CLOCK_MONOTONIC, timestamp);
3397 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003398 }
3399 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003400 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003401 return ret;
3402}
3403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003404static int out_set_callback(struct audio_stream_out *stream,
3405 stream_callback_t callback, void *cookie)
3406{
3407 struct stream_out *out = (struct stream_out *)stream;
3408
3409 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003410 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003411 out->offload_callback = callback;
3412 out->offload_cookie = cookie;
3413 pthread_mutex_unlock(&out->lock);
3414 return 0;
3415}
3416
3417static int out_pause(struct audio_stream_out* stream)
3418{
3419 struct stream_out *out = (struct stream_out *)stream;
3420 int status = -ENOSYS;
3421 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003422 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003423 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003424 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303426 struct audio_device *adev = out->dev;
3427 int snd_scard_state = get_snd_card_state(adev);
3428
3429 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3430 status = compress_pause(out->compr);
3431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003433
Mingming Yin21854652016-04-13 11:54:02 -07003434 if (audio_extn_passthru_is_active()) {
3435 ALOGV("offload use case, pause passthru");
3436 audio_extn_passthru_on_pause(out);
3437 }
3438
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303439 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003440 audio_extn_dts_notify_playback_state(out->usecase, 0,
3441 out->sample_rate, popcount(out->channel_mask),
3442 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 }
3444 pthread_mutex_unlock(&out->lock);
3445 }
3446 return status;
3447}
3448
3449static int out_resume(struct audio_stream_out* stream)
3450{
3451 struct stream_out *out = (struct stream_out *)stream;
3452 int status = -ENOSYS;
3453 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003454 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003455 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003456 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003457 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003458 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303459 struct audio_device *adev = out->dev;
3460 int snd_scard_state = get_snd_card_state(adev);
3461
Mingming Yin21854652016-04-13 11:54:02 -07003462 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3463 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3464 pthread_mutex_lock(&out->dev->lock);
3465 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003466 pthread_mutex_unlock(&out->dev->lock);
3467 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303468 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003469 }
3470 if (!status) {
3471 out->offload_state = OFFLOAD_STATE_PLAYING;
3472 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303473 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003474 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3475 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476 }
3477 pthread_mutex_unlock(&out->lock);
3478 }
3479 return status;
3480}
3481
3482static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3483{
3484 struct stream_out *out = (struct stream_out *)stream;
3485 int status = -ENOSYS;
3486 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003487 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003488 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3490 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3491 else
3492 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3493 pthread_mutex_unlock(&out->lock);
3494 }
3495 return status;
3496}
3497
3498static int out_flush(struct audio_stream_out* stream)
3499{
3500 struct stream_out *out = (struct stream_out *)stream;
3501 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003502 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003503 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003504 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003505 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3506 stop_compressed_output_l(out);
3507 out->written = 0;
3508 } else {
3509 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3510 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003512 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003513 return 0;
3514 }
3515 return -ENOSYS;
3516}
3517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518/** audio_stream_in implementation **/
3519static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3520{
3521 struct stream_in *in = (struct stream_in *)stream;
3522
3523 return in->config.rate;
3524}
3525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003526static int in_set_sample_rate(struct audio_stream *stream __unused,
3527 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528{
3529 return -ENOSYS;
3530}
3531
3532static size_t in_get_buffer_size(const struct audio_stream *stream)
3533{
3534 struct stream_in *in = (struct stream_in *)stream;
3535
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003536 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3537 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003538 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3539 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303540 else if(audio_extn_cin_attached_usecase(in->usecase))
3541 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003542
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003543 return in->config.period_size * in->af_period_multiplier *
3544 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545}
3546
3547static uint32_t in_get_channels(const struct audio_stream *stream)
3548{
3549 struct stream_in *in = (struct stream_in *)stream;
3550
3551 return in->channel_mask;
3552}
3553
3554static audio_format_t in_get_format(const struct audio_stream *stream)
3555{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003556 struct stream_in *in = (struct stream_in *)stream;
3557
3558 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559}
3560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003561static int in_set_format(struct audio_stream *stream __unused,
3562 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563{
3564 return -ENOSYS;
3565}
3566
3567static int in_standby(struct audio_stream *stream)
3568{
3569 struct stream_in *in = (struct stream_in *)stream;
3570 struct audio_device *adev = in->dev;
3571 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303572 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3573 stream, in->usecase, use_case_table[in->usecase]);
3574
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003575 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003576 if (!in->standby && in->is_st_session) {
3577 ALOGD("%s: sound trigger pcm stop lab", __func__);
3578 audio_extn_sound_trigger_stop_lab(in);
3579 in->standby = 1;
3580 }
3581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003583 if (adev->adm_deregister_stream)
3584 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3585
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003586 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003588 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3589 voice_extn_compress_voip_close_input_stream(stream);
3590 ALOGD("VOIP input entered standby");
3591 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303592 if (audio_extn_cin_attached_usecase(in->usecase))
3593 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003594 if (in->pcm) {
3595 pcm_close(in->pcm);
3596 in->pcm = NULL;
3597 }
3598 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003599 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003600 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 }
3602 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003603 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 return status;
3605}
3606
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003607static int in_dump(const struct audio_stream *stream __unused,
3608 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609{
3610 return 0;
3611}
3612
3613static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3614{
3615 struct stream_in *in = (struct stream_in *)stream;
3616 struct audio_device *adev = in->dev;
3617 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003619 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303621 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 parms = str_parms_create_str(kvpairs);
3623
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303624 if (!parms)
3625 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003626 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003627 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003628
3629 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3630 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 val = atoi(value);
3632 /* no audio source uses val == 0 */
3633 if ((in->source != val) && (val != 0)) {
3634 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003635 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3636 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3637 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003638 (in->config.rate == 8000 || in->config.rate == 16000 ||
3639 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003640 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003641 err = voice_extn_compress_voip_open_input_stream(in);
3642 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003643 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003644 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003645 }
3646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648 }
3649
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003650 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3651 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003653 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 in->device = val;
3655 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003656 if (!in->standby && !in->is_st_session) {
3657 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003658 if (adev->adm_on_routing_change)
3659 adev->adm_on_routing_change(adev->adm_data,
3660 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003661 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 }
3664 }
3665
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303666 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3667 if (err >= 0) {
3668 strlcpy(in->profile, value, sizeof(in->profile));
3669 ALOGV("updating stream profile with value '%s'", in->profile);
3670 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3671 &adev->streams_input_cfg_list,
3672 in->device, in->flags, in->format,
3673 in->sample_rate, in->bit_width,
3674 in->profile, &in->app_type_cfg);
3675 }
3676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003678 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679
3680 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303681error:
Eric Laurent994a6932013-07-17 11:51:42 -07003682 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 return ret;
3684}
3685
3686static char* in_get_parameters(const struct audio_stream *stream,
3687 const char *keys)
3688{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003689 struct stream_in *in = (struct stream_in *)stream;
3690 struct str_parms *query = str_parms_create_str(keys);
3691 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003692 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003693
3694 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003695 if (reply) {
3696 str_parms_destroy(reply);
3697 }
3698 if (query) {
3699 str_parms_destroy(query);
3700 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003701 ALOGE("in_get_parameters: failed to create query or reply");
3702 return NULL;
3703 }
3704
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003705 ALOGV("%s: enter: keys - %s", __func__, keys);
3706
3707 voice_extn_in_get_parameters(in, query, reply);
3708
3709 str = str_parms_to_str(reply);
3710 str_parms_destroy(query);
3711 str_parms_destroy(reply);
3712
3713 ALOGV("%s: exit: returns - %s", __func__, str);
3714 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715}
3716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003717static int in_set_gain(struct audio_stream_in *stream __unused,
3718 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719{
3720 return 0;
3721}
3722
3723static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3724 size_t bytes)
3725{
3726 struct stream_in *in = (struct stream_in *)stream;
3727 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303728 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303729 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303730 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003732 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303733
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003734 if (in->is_st_session) {
3735 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3736 /* Read from sound trigger HAL */
3737 audio_extn_sound_trigger_read(in, buffer, bytes);
3738 pthread_mutex_unlock(&in->lock);
3739 return bytes;
3740 }
3741
Ashish Jainbbce4322016-02-16 13:25:27 +05303742 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003743 ALOGD(" %s: sound card is not active/SSR state", __func__);
3744 ret= -EIO;;
3745 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303746 }
3747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003749 pthread_mutex_lock(&adev->lock);
3750 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3751 ret = voice_extn_compress_voip_start_input_stream(in);
3752 else
3753 ret = start_input_stream(in);
3754 pthread_mutex_unlock(&adev->lock);
3755 if (ret != 0) {
3756 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 }
3758 in->standby = 0;
3759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003761 // what's the duration requested by the client?
3762 long ns = 0;
3763
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303764 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003765 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3766 in->config.rate;
3767
3768 request_in_focus(in, ns);
3769 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003770
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303771 if (audio_extn_cin_attached_usecase(in->usecase)) {
3772 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3773 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303774 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003775 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303776 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003777 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003778 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003779 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303780 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003781 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303782 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3783 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3784 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3785 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303786 ret = -EINVAL;
3787 goto exit;
3788 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303789 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303790 ret = -errno;
3791 }
3792 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303793 /* bytes read is always set to bytes for non compress usecases */
3794 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795 }
3796
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003797 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 /*
3800 * Instead of writing zeroes here, we could trust the hardware
3801 * to always provide zeroes when muted.
3802 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303803 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3804 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 memset(buffer, 0, bytes);
3806
3807exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303808 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303809 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003810 if (-ENETRESET == ret)
3811 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 pthread_mutex_unlock(&in->lock);
3814
3815 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303816 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303817 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303818 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303819 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303820 in->standby = true;
3821 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303822 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3823 bytes_read = bytes;
3824 memset(buffer, 0, bytes);
3825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003827 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303828 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303829 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303831 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832}
3833
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003834static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835{
3836 return 0;
3837}
3838
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003839static int add_remove_audio_effect(const struct audio_stream *stream,
3840 effect_handle_t effect,
3841 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003843 struct stream_in *in = (struct stream_in *)stream;
3844 int status = 0;
3845 effect_descriptor_t desc;
3846
3847 status = (*effect)->get_descriptor(effect, &desc);
3848 if (status != 0)
3849 return status;
3850
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003851 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003852 pthread_mutex_lock(&in->dev->lock);
3853 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3854 in->enable_aec != enable &&
3855 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3856 in->enable_aec = enable;
3857 if (!in->standby)
3858 select_devices(in->dev, in->usecase);
3859 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003860 if (in->enable_ns != enable &&
3861 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3862 in->enable_ns = enable;
3863 if (!in->standby)
3864 select_devices(in->dev, in->usecase);
3865 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003866 pthread_mutex_unlock(&in->dev->lock);
3867 pthread_mutex_unlock(&in->lock);
3868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 return 0;
3870}
3871
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003872static int in_add_audio_effect(const struct audio_stream *stream,
3873 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874{
Eric Laurent994a6932013-07-17 11:51:42 -07003875 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003876 return add_remove_audio_effect(stream, effect, true);
3877}
3878
3879static int in_remove_audio_effect(const struct audio_stream *stream,
3880 effect_handle_t effect)
3881{
Eric Laurent994a6932013-07-17 11:51:42 -07003882 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003883 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884}
3885
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303886int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 audio_io_handle_t handle,
3888 audio_devices_t devices,
3889 audio_output_flags_t flags,
3890 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003891 struct audio_stream_out **stream_out,
3892 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893{
3894 struct audio_device *adev = (struct audio_device *)dev;
3895 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303896 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003897 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303900
3901 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3902 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003903 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303904 return -EINVAL;
3905 }
3906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3908
Mingming Yin3a941d42016-02-17 18:08:05 -08003909 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3910 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303911 devices, flags, &out->stream);
3912
3913
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003914 if (!out) {
3915 return -ENOMEM;
3916 }
3917
Haynes Mathew George204045b2015-02-25 20:32:03 -08003918 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003919 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003920 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922 if (devices == AUDIO_DEVICE_NONE)
3923 devices = AUDIO_DEVICE_OUT_SPEAKER;
3924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 out->flags = flags;
3926 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003927 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003928 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003929 out->sample_rate = config->sample_rate;
3930 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3931 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003932 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003933 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003934 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303935 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936
Mingming Yin3a941d42016-02-17 18:08:05 -08003937 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3938 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3939 pthread_mutex_lock(&adev->lock);
3940 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3941 ret = read_hdmi_sink_caps(out);
3942 pthread_mutex_unlock(&adev->lock);
3943 if (ret != 0) {
3944 if (ret == -ENOSYS) {
3945 /* ignore and go with default */
3946 ret = 0;
3947 } else {
3948 ALOGE("error reading hdmi sink caps");
3949 goto error_open;
3950 }
3951 }
3952 }
3953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303955 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003956 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003957 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003958 ret = voice_extn_compress_voip_open_output_stream(out);
3959 if (ret != 0) {
3960 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3961 __func__, ret);
3962 goto error_open;
3963 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003964 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05303965 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003966
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003967 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3968 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3969 ALOGE("%s: Unsupported Offload information", __func__);
3970 ret = -EINVAL;
3971 goto error_open;
3972 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003973
Mingming Yin3a941d42016-02-17 18:08:05 -08003974 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003975 if(config->offload_info.format == 0)
3976 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003977 if (config->offload_info.sample_rate == 0)
3978 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003979 }
3980
Mingming Yin90310102013-11-13 16:57:00 -08003981 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303982 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003983 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 ret = -EINVAL;
3985 goto error_open;
3986 }
3987
3988 out->compr_config.codec = (struct snd_codec *)
3989 calloc(1, sizeof(struct snd_codec));
3990
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003991 if (!out->compr_config.codec) {
3992 ret = -ENOMEM;
3993 goto error_open;
3994 }
3995
Dhananjay Kumarac341582017-02-23 23:42:25 +05303996 out->stream.pause = out_pause;
3997 out->stream.resume = out_resume;
3998 out->stream.flush = out_flush;
3999 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004000 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004001 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304002 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004003 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304004 } else {
4005 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4006 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004007 }
vivek mehta446c3962015-09-14 10:57:35 -07004008
4009 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004010 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4011 config->format == 0 && config->sample_rate == 0 &&
4012 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004013 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004014 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4015 } else {
4016 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4017 ret = -EEXIST;
4018 goto error_open;
4019 }
vivek mehta446c3962015-09-14 10:57:35 -07004020 }
4021
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004022 if (config->offload_info.channel_mask)
4023 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004024 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004025 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004026 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004027 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304028 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004029 ret = -EINVAL;
4030 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004031 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004032
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004033 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004034 out->sample_rate = config->offload_info.sample_rate;
4035
Mingming Yin3ee55c62014-08-04 14:23:35 -07004036 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004037
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304038 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4039 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4040 audio_extn_dolby_send_ddp_endp_params(adev);
4041 audio_extn_dolby_set_dmid(adev);
4042 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004045 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004046 out->compr_config.codec->bit_rate =
4047 config->offload_info.bit_rate;
4048 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304049 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304051 /* Update bit width only for non passthrough usecases.
4052 * For passthrough usecases, the output will always be opened @16 bit
4053 */
4054 if (!audio_extn_passthru_is_passthrough_stream(out))
4055 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004056 /*TODO: Do we need to change it for passthrough */
4057 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004058
Manish Dewangana6fc5442015-08-24 20:30:31 +05304059 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4060 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304061 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304062 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304063 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4064 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304065
4066 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4067 AUDIO_FORMAT_PCM) {
4068
4069 /*Based on platform support, configure appropriate alsa format for corresponding
4070 *hal input format.
4071 */
4072 out->compr_config.codec->format = hal_format_to_alsa(
4073 config->offload_info.format);
4074
Ashish Jain83a6cc22016-06-28 14:34:17 +05304075 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304076 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304077 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304078
Dhananjay Kumarac341582017-02-23 23:42:25 +05304079 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304080 *hal input format and alsa format might differ based on platform support.
4081 */
4082 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304083 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304084
4085 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4086
4087 /* Check if alsa session is configured with the same format as HAL input format,
4088 * if not then derive correct fragment size needed to accomodate the
4089 * conversion of HAL input format to alsa format.
4090 */
4091 audio_extn_utils_update_direct_pcm_fragment_size(out);
4092
4093 /*if hal input and output fragment size is different this indicates HAL input format is
4094 *not same as the alsa format
4095 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304096 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304097 /*Allocate a buffer to convert input data to the alsa configured format.
4098 *size of convert buffer is equal to the size required to hold one fragment size
4099 *worth of pcm data, this is because flinger does not write more than fragment_size
4100 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304101 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4102 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304103 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4104 ret = -ENOMEM;
4105 goto error_open;
4106 }
4107 }
4108 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4109 out->compr_config.fragment_size =
4110 audio_extn_passthru_get_buffer_size(&config->offload_info);
4111 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4112 } else {
4113 out->compr_config.fragment_size =
4114 platform_get_compress_offload_buffer_size(&config->offload_info);
4115 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4116 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004117
Amit Shekhar6f461b12014-08-01 14:52:58 -07004118 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304119 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004120
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304121 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4122 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4123 }
4124
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004125 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4126 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004127
Alexy Josephaa54c872014-12-03 02:46:47 -08004128
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004129 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304130 out->send_next_track_params = false;
4131 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004132 out->offload_state = OFFLOAD_STATE_IDLE;
4133 out->playback_started = 0;
4134
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004135 audio_extn_dts_create_state_notifier_node(out->usecase);
4136
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004137 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4138 __func__, config->offload_info.version,
4139 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304140
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304141 /* Check if DSD audio format is supported in codec
4142 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304143 */
4144
4145 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304146 (!platform_check_codec_dsd_support(adev->platform) ||
4147 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304148 ret = -EINVAL;
4149 goto error_open;
4150 }
4151
Ashish Jain5106d362016-05-11 19:23:33 +05304152 /* Disable gapless if any of the following is true
4153 * passthrough playback
4154 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304155 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304156 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304157 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304158 (config->format == AUDIO_FORMAT_DSD) ||
4159 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304160 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304161 check_and_set_gapless_mode(adev, false);
4162 } else
4163 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004164
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304165 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004166 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4167 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304168 if (config->format == AUDIO_FORMAT_DSD) {
4169 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4170 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4171 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004172
4173 create_offload_callback_thread(out);
4174
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004175 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304176 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004177 if (ret != 0) {
4178 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4179 __func__, ret);
4180 goto error_open;
4181 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004182 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4183 if (config->sample_rate == 0)
4184 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4185 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4186 config->sample_rate != 8000) {
4187 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4188 ret = -EINVAL;
4189 goto error_open;
4190 }
4191 out->sample_rate = config->sample_rate;
4192 out->config.rate = config->sample_rate;
4193 if (config->format == AUDIO_FORMAT_DEFAULT)
4194 config->format = AUDIO_FORMAT_PCM_16_BIT;
4195 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4196 config->format = AUDIO_FORMAT_PCM_16_BIT;
4197 ret = -EINVAL;
4198 goto error_open;
4199 }
4200 out->format = config->format;
4201 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4202 out->config = pcm_config_afe_proxy_playback;
4203 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004204 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304205 unsigned int channels = 0;
4206 /*Update config params to default if not set by the caller*/
4207 if (config->sample_rate == 0)
4208 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4209 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4210 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4211 if (config->format == AUDIO_FORMAT_DEFAULT)
4212 config->format = AUDIO_FORMAT_PCM_16_BIT;
4213
4214 channels = audio_channel_count_from_out_mask(out->channel_mask);
4215
Ashish Jain83a6cc22016-06-28 14:34:17 +05304216 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4217 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004218 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4219 out->flags);
4220 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304221 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4222 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4223 out->config = pcm_config_low_latency;
4224 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4225 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4226 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304227 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4228 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4229 if (out->config.period_size <= 0) {
4230 ALOGE("Invalid configuration period size is not valid");
4231 ret = -EINVAL;
4232 goto error_open;
4233 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304234 } else {
4235 /* primary path is the default path selected if no other outputs are available/suitable */
4236 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4237 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4238 }
4239 out->hal_ip_format = format = out->format;
4240 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4241 out->hal_op_format = pcm_format_to_hal(out->config.format);
4242 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4243 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004244 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304245 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304246 if (out->hal_ip_format != out->hal_op_format) {
4247 uint32_t buffer_size = out->config.period_size *
4248 format_to_bitwidth_table[out->hal_op_format] *
4249 out->config.channels;
4250 out->convert_buffer = calloc(1, buffer_size);
4251 if (out->convert_buffer == NULL){
4252 ALOGE("Allocation failed for convert buffer for size %d",
4253 out->compr_config.fragment_size);
4254 ret = -ENOMEM;
4255 goto error_open;
4256 }
4257 ALOGD("Convert buffer allocated of size %d", buffer_size);
4258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 }
4260
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004261 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4262 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304263
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004264 /* TODO remove this hardcoding and check why width is zero*/
4265 if (out->bit_width == 0)
4266 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304267 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004268 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304269 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304270 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304271 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004272 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4273 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4274 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004275 if(adev->primary_output == NULL)
4276 adev->primary_output = out;
4277 else {
4278 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004279 ret = -EEXIST;
4280 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004281 }
4282 }
4283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 /* Check if this usecase is already existing */
4285 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004286 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4287 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004288 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004290 ret = -EEXIST;
4291 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 pthread_mutex_unlock(&adev->lock);
4295
4296 out->stream.common.get_sample_rate = out_get_sample_rate;
4297 out->stream.common.set_sample_rate = out_set_sample_rate;
4298 out->stream.common.get_buffer_size = out_get_buffer_size;
4299 out->stream.common.get_channels = out_get_channels;
4300 out->stream.common.get_format = out_get_format;
4301 out->stream.common.set_format = out_set_format;
4302 out->stream.common.standby = out_standby;
4303 out->stream.common.dump = out_dump;
4304 out->stream.common.set_parameters = out_set_parameters;
4305 out->stream.common.get_parameters = out_get_parameters;
4306 out->stream.common.add_audio_effect = out_add_audio_effect;
4307 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4308 out->stream.get_latency = out_get_latency;
4309 out->stream.set_volume = out_set_volume;
4310 out->stream.write = out_write;
4311 out->stream.get_render_position = out_get_render_position;
4312 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004313 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004315 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004317 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004318 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319
4320 config->format = out->stream.common.get_format(&out->stream.common);
4321 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4322 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4323
4324 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304325 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004326 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004327
4328 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4329 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4330 popcount(out->channel_mask), out->playback_started);
4331
Eric Laurent994a6932013-07-17 11:51:42 -07004332 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004334
4335error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304336 if (out->convert_buffer)
4337 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004338 free(out);
4339 *stream_out = NULL;
4340 ALOGD("%s: exit: ret %d", __func__, ret);
4341 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342}
4343
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304344void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345 struct audio_stream_out *stream)
4346{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004347 struct stream_out *out = (struct stream_out *)stream;
4348 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004349 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004350
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304351 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4352
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004353 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304354 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004355 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304356 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004357 if(ret != 0)
4358 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4359 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004360 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004361 out_standby(&stream->common);
4362
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004363 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004364 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004365 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004366 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004367 if (out->compr_config.codec != NULL)
4368 free(out->compr_config.codec);
4369 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004370
Ashish Jain83a6cc22016-06-28 14:34:17 +05304371 if (out->convert_buffer != NULL) {
4372 free(out->convert_buffer);
4373 out->convert_buffer = NULL;
4374 }
4375
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004376 if (adev->voice_tx_output == out)
4377 adev->voice_tx_output = NULL;
4378
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304379 if (adev->primary_output == out)
4380 adev->primary_output = NULL;
4381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004382 pthread_cond_destroy(&out->cond);
4383 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004385 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386}
4387
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004388static void close_compress_sessions(struct audio_device *adev)
4389{
Mingming Yin7b762e72015-03-04 13:47:32 -08004390 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304391 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004392 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004393 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304394
4395 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004396 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304397 if (is_offload_usecase(usecase->id)) {
4398 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004399 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4400 out = usecase->stream.out;
4401 pthread_mutex_unlock(&adev->lock);
4402 out_standby(&out->stream.common);
4403 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004404 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004405 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304406 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004407 }
4408 pthread_mutex_unlock(&adev->lock);
4409}
4410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4412{
4413 struct audio_device *adev = (struct audio_device *)dev;
4414 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004416 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004417 int ret;
4418 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004420 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304423 if (!parms)
4424 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004425 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4426 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304427 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304428 if (strstr(snd_card_status, "OFFLINE")) {
4429 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304430 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004431 //close compress sessions on OFFLINE status
4432 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304433 } else if (strstr(snd_card_status, "ONLINE")) {
4434 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304435 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004436 //send dts hpx license if enabled
4437 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304438 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304439 }
4440
4441 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004442 status = voice_set_parameters(adev, parms);
4443 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004444 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004446 status = platform_set_parameters(adev->platform, parms);
4447 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004448 goto done;
4449
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004450 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4451 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004452 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4454 adev->bluetooth_nrec = true;
4455 else
4456 adev->bluetooth_nrec = false;
4457 }
4458
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004459 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4460 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4462 adev->screen_off = false;
4463 else
4464 adev->screen_off = true;
4465 }
4466
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004467 ret = str_parms_get_int(parms, "rotation", &val);
4468 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004469 bool reverse_speakers = false;
4470 switch(val) {
4471 // FIXME: note that the code below assumes that the speakers are in the correct placement
4472 // relative to the user when the device is rotated 90deg from its default rotation. This
4473 // assumption is device-specific, not platform-specific like this code.
4474 case 270:
4475 reverse_speakers = true;
4476 break;
4477 case 0:
4478 case 90:
4479 case 180:
4480 break;
4481 default:
4482 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004483 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004484 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004485 if (status == 0) {
4486 if (adev->speaker_lr_swap != reverse_speakers) {
4487 adev->speaker_lr_swap = reverse_speakers;
4488 // only update the selected device if there is active pcm playback
4489 struct audio_usecase *usecase;
4490 struct listnode *node;
4491 list_for_each(node, &adev->usecase_list) {
4492 usecase = node_to_item(node, struct audio_usecase, list);
4493 if (usecase->type == PCM_PLAYBACK) {
4494 select_devices(adev, usecase->id);
4495 break;
4496 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004497 }
4498 }
4499 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004500 }
4501
Mingming Yin514a8bc2014-07-29 15:22:21 -07004502 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4503 if (ret >= 0) {
4504 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4505 adev->bt_wb_speech_enabled = true;
4506 else
4507 adev->bt_wb_speech_enabled = false;
4508 }
4509
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004510 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4511 if (ret >= 0) {
4512 val = atoi(value);
4513 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004514 ALOGV("cache new ext disp type and edid");
4515 ret = platform_get_ext_disp_type(adev->platform);
4516 if (ret < 0) {
4517 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004518 status = ret;
4519 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004520 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004521 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004522 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004523 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004524 /*
4525 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4526 * Per AudioPolicyManager, USB device is higher priority than WFD.
4527 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4528 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4529 * starting voice call on USB
4530 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004531 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4532 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004533 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4534 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004535 }
vivek mehta344576a2016-04-12 18:56:03 -07004536 ALOGV("detected USB connect .. disable proxy");
4537 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004538 }
4539 }
4540
4541 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4542 if (ret >= 0) {
4543 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004544 /*
4545 * The HDMI / Displayport disconnect handling has been moved to
4546 * audio extension to ensure that its parameters are not
4547 * invalidated prior to updating sysfs of the disconnect event
4548 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4549 */
4550 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004551 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004552 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4553 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304554 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4555 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004556 }
vivek mehta344576a2016-04-12 18:56:03 -07004557 ALOGV("detected USB disconnect .. enable proxy");
4558 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004559 }
4560 }
4561
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304562 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4563 if (ret >= 0) {
4564 struct audio_usecase *usecase;
4565 struct listnode *node;
4566 list_for_each(node, &adev->usecase_list) {
4567 usecase = node_to_item(node, struct audio_usecase, list);
4568 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004569 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304570 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304571 lock_output_stream(usecase->stream.out);
4572 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304573 //force device switch to re configure encoder
4574 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304575 audio_extn_a2dp_set_handoff_mode(false);
4576 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304577 break;
4578 }
4579 }
4580 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004581
4582 //handle vr audio setparam
4583 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4584 value, sizeof(value));
4585 if (ret >= 0) {
4586 ALOGI("Setting vr mode to be %s", value);
4587 if (!strncmp(value, "true", 4)) {
4588 adev->vr_audio_mode_enabled = true;
4589 ALOGI("Setting vr mode to true");
4590 } else if (!strncmp(value, "false", 5)) {
4591 adev->vr_audio_mode_enabled = false;
4592 ALOGI("Setting vr mode to false");
4593 } else {
4594 ALOGI("wrong vr mode set");
4595 }
4596 }
4597
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304598 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004599done:
4600 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004601 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304602error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004603 ALOGV("%s: exit with code(%d)", __func__, status);
4604 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605}
4606
4607static char* adev_get_parameters(const struct audio_hw_device *dev,
4608 const char *keys)
4609{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004610 struct audio_device *adev = (struct audio_device *)dev;
4611 struct str_parms *reply = str_parms_create();
4612 struct str_parms *query = str_parms_create_str(keys);
4613 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304614 char value[256] = {0};
4615 int ret = 0;
4616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004617 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004618 if (reply) {
4619 str_parms_destroy(reply);
4620 }
4621 if (query) {
4622 str_parms_destroy(query);
4623 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004624 ALOGE("adev_get_parameters: failed to create query or reply");
4625 return NULL;
4626 }
4627
Naresh Tannirud7205b62014-06-20 02:54:48 +05304628 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4629 sizeof(value));
4630 if (ret >=0) {
4631 int val = 1;
4632 pthread_mutex_lock(&adev->snd_card_status.lock);
4633 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4634 val = 0;
4635 pthread_mutex_unlock(&adev->snd_card_status.lock);
4636 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4637 goto exit;
4638 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004639 //handle vr audio getparam
4640
4641 ret = str_parms_get_str(query,
4642 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4643 value, sizeof(value));
4644
4645 if (ret >= 0) {
4646 bool vr_audio_enabled = false;
4647 pthread_mutex_lock(&adev->lock);
4648 vr_audio_enabled = adev->vr_audio_mode_enabled;
4649 pthread_mutex_unlock(&adev->lock);
4650
4651 ALOGI("getting vr mode to %d", vr_audio_enabled);
4652
4653 if (vr_audio_enabled) {
4654 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4655 "true");
4656 goto exit;
4657 } else {
4658 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4659 "false");
4660 goto exit;
4661 }
4662 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004663
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004664 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004665 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004666 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004667 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304668 pthread_mutex_unlock(&adev->lock);
4669
Naresh Tannirud7205b62014-06-20 02:54:48 +05304670exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004671 str = str_parms_to_str(reply);
4672 str_parms_destroy(query);
4673 str_parms_destroy(reply);
4674
4675 ALOGV("%s: exit: returns - %s", __func__, str);
4676 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677}
4678
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004679static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680{
4681 return 0;
4682}
4683
4684static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4685{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004686 int ret;
4687 struct audio_device *adev = (struct audio_device *)dev;
4688 pthread_mutex_lock(&adev->lock);
4689 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004690 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004691 pthread_mutex_unlock(&adev->lock);
4692 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693}
4694
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004695static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4696 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697{
4698 return -ENOSYS;
4699}
4700
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004701static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4702 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703{
4704 return -ENOSYS;
4705}
4706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004707static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4708 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709{
4710 return -ENOSYS;
4711}
4712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004713static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4714 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715{
4716 return -ENOSYS;
4717}
4718
4719static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4720{
4721 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 pthread_mutex_lock(&adev->lock);
4724 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004725 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004727 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004728 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004729 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004730 adev->current_call_output = NULL;
4731 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004732 }
4733 pthread_mutex_unlock(&adev->lock);
4734 return 0;
4735}
4736
4737static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4738{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004739 int ret;
4740
4741 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004742 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004743 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4744 pthread_mutex_unlock(&adev->lock);
4745
4746 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747}
4748
4749static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4750{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004751 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752 return 0;
4753}
4754
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004755static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 const struct audio_config *config)
4757{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004758 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004759
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004760 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4761 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762}
4763
4764static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004765 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 audio_devices_t devices,
4767 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004768 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304769 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004770 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004771 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772{
4773 struct audio_device *adev = (struct audio_device *)dev;
4774 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004775 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004776 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004777 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304778 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304781 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4782 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304784 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785
4786 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004787
4788 if (!in) {
4789 ALOGE("failed to allocate input stream");
4790 return -ENOMEM;
4791 }
4792
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304793 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304794 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4795 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004796 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004797 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799 in->stream.common.get_sample_rate = in_get_sample_rate;
4800 in->stream.common.set_sample_rate = in_set_sample_rate;
4801 in->stream.common.get_buffer_size = in_get_buffer_size;
4802 in->stream.common.get_channels = in_get_channels;
4803 in->stream.common.get_format = in_get_format;
4804 in->stream.common.set_format = in_set_format;
4805 in->stream.common.standby = in_standby;
4806 in->stream.common.dump = in_dump;
4807 in->stream.common.set_parameters = in_set_parameters;
4808 in->stream.common.get_parameters = in_get_parameters;
4809 in->stream.common.add_audio_effect = in_add_audio_effect;
4810 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4811 in->stream.set_gain = in_set_gain;
4812 in->stream.read = in_read;
4813 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4814
4815 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004816 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 in->standby = 1;
4819 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004820 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004821 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304823 in->usecase = USECASE_AUDIO_RECORD;
4824 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4825 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4826 is_low_latency = true;
4827#if LOW_LATENCY_CAPTURE_USE_CASE
4828 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4829#endif
4830 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4831 }
4832
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004833 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004834 if (in->realtime) {
4835 in->config = pcm_config_audio_capture_rt;
4836 in->sample_rate = in->config.rate;
4837 in->af_period_multiplier = af_period_multiplier;
4838 } else {
4839 in->config = pcm_config_audio_capture;
4840 in->config.rate = config->sample_rate;
4841 in->sample_rate = config->sample_rate;
4842 in->af_period_multiplier = 1;
4843 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304844 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304846 /* restrict 24 bit capture for unprocessed source only
4847 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4848 */
4849 if (config->format == AUDIO_FORMAT_DEFAULT) {
4850 config->format = AUDIO_FORMAT_PCM_16_BIT;
4851 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4852 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4853 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4854 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4855 bool ret_error = false;
4856 in->bit_width = 24;
4857 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4858 from HAL is 24_packed and 8_24
4859 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4860 24_packed return error indicating supported format is 24_packed
4861 *> In case of any other source requesting 24 bit or float return error
4862 indicating format supported is 16 bit only.
4863
4864 on error flinger will retry with supported format passed
4865 */
4866 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4867 (source != AUDIO_SOURCE_CAMCORDER)) {
4868 config->format = AUDIO_FORMAT_PCM_16_BIT;
4869 if (config->sample_rate > 48000)
4870 config->sample_rate = 48000;
4871 ret_error = true;
4872 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4873 in->config.format = PCM_FORMAT_S24_3LE;
4874 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4875 in->config.format = PCM_FORMAT_S24_LE;
4876 } else {
4877 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4878 ret_error = true;
4879 }
4880
4881 if (ret_error) {
4882 ret = -EINVAL;
4883 goto err_open;
4884 }
4885 }
4886
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304887 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304888 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4889 (adev->mode != AUDIO_MODE_IN_CALL)) {
4890 ret = -EINVAL;
4891 goto err_open;
4892 }
4893
4894 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4895 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004896 if (config->sample_rate == 0)
4897 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4898 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4899 config->sample_rate != 8000) {
4900 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4901 ret = -EINVAL;
4902 goto err_open;
4903 }
4904 if (config->format == AUDIO_FORMAT_DEFAULT)
4905 config->format = AUDIO_FORMAT_PCM_16_BIT;
4906 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4907 config->format = AUDIO_FORMAT_PCM_16_BIT;
4908 ret = -EINVAL;
4909 goto err_open;
4910 }
4911
4912 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4913 in->config = pcm_config_afe_proxy_record;
4914 in->config.channels = channel_count;
4915 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304916 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304917 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4918 in, config, &channel_mask_updated)) {
4919 if (channel_mask_updated == true) {
4920 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4921 __func__, config->channel_mask);
4922 ret = -EINVAL;
4923 goto err_open;
4924 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304925 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004926 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004927 audio_extn_compr_cap_format_supported(config->format) &&
4928 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004929 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304930 } else if (audio_extn_cin_applicable_stream(in)) {
4931 ret = audio_extn_cin_configure_input_stream(in);
4932 if (ret)
4933 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004934 } else {
4935 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004936 if (!in->realtime) {
4937 in->format = config->format;
4938 frame_size = audio_stream_in_frame_size(&in->stream);
4939 buffer_size = get_input_buffer_size(config->sample_rate,
4940 config->format,
4941 channel_count,
4942 is_low_latency);
4943 in->config.period_size = buffer_size / frame_size;
4944 }
4945
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004946 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004947 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004948 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004949 (in->config.rate == 8000 || in->config.rate == 16000 ||
4950 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004951 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4952 voice_extn_compress_voip_open_input_stream(in);
4953 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304956 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4957 &adev->streams_input_cfg_list,
4958 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304959 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304960
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004961 /* This stream could be for sound trigger lab,
4962 get sound trigger pcm if present */
4963 audio_extn_sound_trigger_check_and_get_session(in);
4964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004965 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004966 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004967 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968
4969err_open:
4970 free(in);
4971 *stream_in = NULL;
4972 return ret;
4973}
4974
4975static void adev_close_input_stream(struct audio_hw_device *dev,
4976 struct audio_stream_in *stream)
4977{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004978 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004979 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004980 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304981
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304982 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004983
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304984 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004985 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304986
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004987 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304988 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004989 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304990 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004991 if (ret != 0)
4992 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4993 __func__, ret);
4994 } else
4995 in_standby(&stream->common);
4996
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004997 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004998 audio_extn_ssr_deinit();
4999 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305001 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005002 audio_extn_compr_cap_format_supported(in->config.format))
5003 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305004
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305005 if (audio_extn_cin_attached_usecase(in->usecase))
5006 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005007
Mingming Yinfd7607b2016-01-22 12:48:44 -08005008 if (in->is_st_session) {
5009 ALOGV("%s: sound trigger pcm stop lab", __func__);
5010 audio_extn_sound_trigger_stop_lab(in);
5011 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005012 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013 return;
5014}
5015
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005016static int adev_dump(const audio_hw_device_t *device __unused,
5017 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005018{
5019 return 0;
5020}
5021
5022static int adev_close(hw_device_t *device)
5023{
5024 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005025
5026 if (!adev)
5027 return 0;
5028
5029 pthread_mutex_lock(&adev_init_lock);
5030
5031 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005032 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005033 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305034 audio_extn_utils_release_streams_cfg_lists(
5035 &adev->streams_output_cfg_list,
5036 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305037 if (audio_extn_qaf_is_enabled())
5038 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005039 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005040 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005041 free(adev->snd_dev_ref_cnt);
5042 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005043 if (adev->adm_deinit)
5044 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305045 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005046 free(device);
5047 adev = NULL;
5048 }
5049 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005051 return 0;
5052}
5053
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005054/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5055 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5056 * just that it _might_ work.
5057 */
5058static int period_size_is_plausible_for_low_latency(int period_size)
5059{
5060 switch (period_size) {
5061 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005062 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005063 case 240:
5064 case 320:
5065 case 480:
5066 return 1;
5067 default:
5068 return 0;
5069 }
5070}
5071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072static int adev_open(const hw_module_t *module, const char *name,
5073 hw_device_t **device)
5074{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305075 int ret;
5076
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005077 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005078 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5079
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005080 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005081 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005082 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005083 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005084 ALOGD("%s: returning existing instance of adev", __func__);
5085 ALOGD("%s: exit", __func__);
5086 pthread_mutex_unlock(&adev_init_lock);
5087 return 0;
5088 }
5089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005090 adev = calloc(1, sizeof(struct audio_device));
5091
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005092 if (!adev) {
5093 pthread_mutex_unlock(&adev_init_lock);
5094 return -ENOMEM;
5095 }
5096
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005097 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005099 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5100 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5101 adev->device.common.module = (struct hw_module_t *)module;
5102 adev->device.common.close = adev_close;
5103
5104 adev->device.init_check = adev_init_check;
5105 adev->device.set_voice_volume = adev_set_voice_volume;
5106 adev->device.set_master_volume = adev_set_master_volume;
5107 adev->device.get_master_volume = adev_get_master_volume;
5108 adev->device.set_master_mute = adev_set_master_mute;
5109 adev->device.get_master_mute = adev_get_master_mute;
5110 adev->device.set_mode = adev_set_mode;
5111 adev->device.set_mic_mute = adev_set_mic_mute;
5112 adev->device.get_mic_mute = adev_get_mic_mute;
5113 adev->device.set_parameters = adev_set_parameters;
5114 adev->device.get_parameters = adev_get_parameters;
5115 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5116 adev->device.open_output_stream = adev_open_output_stream;
5117 adev->device.close_output_stream = adev_close_output_stream;
5118 adev->device.open_input_stream = adev_open_input_stream;
5119 adev->device.close_input_stream = adev_close_input_stream;
5120 adev->device.dump = adev_dump;
5121
5122 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005123 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005124 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005125 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005128 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005129 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005130 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005131 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005132 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005133 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005134 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005135 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305136 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305137 adev->perf_lock_opts[0] = 0x101;
5138 adev->perf_lock_opts[1] = 0x20E;
5139 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305140
5141 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5142 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005144 adev->platform = platform_init(adev);
5145 if (!adev->platform) {
5146 free(adev->snd_dev_ref_cnt);
5147 free(adev);
5148 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5149 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005150 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305151 pthread_mutex_destroy(&adev->lock);
5152 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005153 return -EINVAL;
5154 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005155
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305156 if (audio_extn_qaf_is_enabled()) {
5157 ret = audio_extn_qaf_init(adev);
5158 if (ret < 0) {
5159 free(adev);
5160 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5161 *device = NULL;
5162 pthread_mutex_unlock(&adev_init_lock);
5163 pthread_mutex_destroy(&adev->lock);
5164 return ret;
5165 }
5166
5167 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5168 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5169 }
5170
Naresh Tanniru4c630392014-05-12 01:05:52 +05305171 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5172
Eric Laurentc4aef752013-09-12 17:45:53 -07005173 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5174 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5175 if (adev->visualizer_lib == NULL) {
5176 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5177 } else {
5178 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5179 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005180 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005181 "visualizer_hal_start_output");
5182 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005183 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005184 "visualizer_hal_stop_output");
5185 }
5186 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305187 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005188 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005189 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005190 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005191
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005192 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5193 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5194 if (adev->offload_effects_lib == NULL) {
5195 ALOGE("%s: DLOPEN failed for %s", __func__,
5196 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5197 } else {
5198 ALOGV("%s: DLOPEN successful for %s", __func__,
5199 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5200 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305201 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005202 "offload_effects_bundle_hal_start_output");
5203 adev->offload_effects_stop_output =
5204 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5205 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005206 adev->offload_effects_set_hpx_state =
5207 (int (*)(bool))dlsym(adev->offload_effects_lib,
5208 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305209 adev->offload_effects_get_parameters =
5210 (void (*)(struct str_parms *, struct str_parms *))
5211 dlsym(adev->offload_effects_lib,
5212 "offload_effects_bundle_get_parameters");
5213 adev->offload_effects_set_parameters =
5214 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5215 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005216 }
5217 }
5218
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005219 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5220 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5221 if (adev->adm_lib == NULL) {
5222 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5223 } else {
5224 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5225 adev->adm_init = (adm_init_t)
5226 dlsym(adev->adm_lib, "adm_init");
5227 adev->adm_deinit = (adm_deinit_t)
5228 dlsym(adev->adm_lib, "adm_deinit");
5229 adev->adm_register_input_stream = (adm_register_input_stream_t)
5230 dlsym(adev->adm_lib, "adm_register_input_stream");
5231 adev->adm_register_output_stream = (adm_register_output_stream_t)
5232 dlsym(adev->adm_lib, "adm_register_output_stream");
5233 adev->adm_deregister_stream = (adm_deregister_stream_t)
5234 dlsym(adev->adm_lib, "adm_deregister_stream");
5235 adev->adm_request_focus = (adm_request_focus_t)
5236 dlsym(adev->adm_lib, "adm_request_focus");
5237 adev->adm_abandon_focus = (adm_abandon_focus_t)
5238 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005239 adev->adm_set_config = (adm_set_config_t)
5240 dlsym(adev->adm_lib, "adm_set_config");
5241 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5242 dlsym(adev->adm_lib, "adm_request_focus_v2");
5243 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5244 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5245 adev->adm_on_routing_change = (adm_on_routing_change_t)
5246 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005247 }
5248 }
5249
Mingming Yin514a8bc2014-07-29 15:22:21 -07005250 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005251 //initialize this to false for now,
5252 //this will be set to true through set param
5253 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005254
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005255 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005256 *device = &adev->device.common;
5257
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305258 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5259 &adev->streams_output_cfg_list,
5260 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005261
Kiran Kandi910e1862013-10-29 13:29:42 -07005262 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005263
5264 char value[PROPERTY_VALUE_MAX];
5265 int trial;
5266 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5267 trial = atoi(value);
5268 if (period_size_is_plausible_for_low_latency(trial)) {
5269 pcm_config_low_latency.period_size = trial;
5270 pcm_config_low_latency.start_threshold = trial / 4;
5271 pcm_config_low_latency.avail_min = trial / 4;
5272 configured_low_latency_capture_period_size = trial;
5273 }
5274 }
5275 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5276 trial = atoi(value);
5277 if (period_size_is_plausible_for_low_latency(trial)) {
5278 configured_low_latency_capture_period_size = trial;
5279 }
5280 }
5281
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005282 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5283 af_period_multiplier = atoi(value);
5284 if (af_period_multiplier < 0)
5285 af_period_multiplier = 2;
5286 else if (af_period_multiplier > 4)
5287 af_period_multiplier = 4;
5288
5289 ALOGV("new period_multiplier = %d", af_period_multiplier);
5290 }
5291
vivek mehta446c3962015-09-14 10:57:35 -07005292 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005293 pthread_mutex_unlock(&adev_init_lock);
5294
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005295 if (adev->adm_init)
5296 adev->adm_data = adev->adm_init();
5297
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305298 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305299 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005300 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005301 return 0;
5302}
5303
5304static struct hw_module_methods_t hal_module_methods = {
5305 .open = adev_open,
5306};
5307
5308struct audio_module HAL_MODULE_INFO_SYM = {
5309 .common = {
5310 .tag = HARDWARE_MODULE_TAG,
5311 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5312 .hal_api_version = HARDWARE_HAL_API_VERSION,
5313 .id = AUDIO_HARDWARE_MODULE_ID,
5314 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005315 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005316 .methods = &hal_module_methods,
5317 },
5318};