blob: 627be8eee042977a043244a18f8c03c2947de04c [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];
1041 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001042 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301043 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 /*
1045 * This function is to make sure that all the usecases that are active on
1046 * the hardware codec backend are always routed to any one device that is
1047 * handled by the hardware codec.
1048 * For example, if low-latency and deep-buffer usecases are currently active
1049 * on speaker and out_set_parameters(headset) is received on low-latency
1050 * output, then we have to make sure deep-buffer is also switched to headset,
1051 * because of the limitation that both the devices cannot be enabled
1052 * at the same time as they share the same backend.
1053 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001054 /*
1055 * This call is to check if we need to force routing for a particular stream
1056 * If there is a backend configuration change for the device when a
1057 * new stream starts, then ADM needs to be closed and re-opened with the new
1058 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001059 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001060 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001061 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1062 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301063 /* For a2dp device reconfigure all active sessions
1064 * with new AFE encoder format based on a2dp state
1065 */
1066 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1067 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1068 audio_extn_a2dp_is_force_device_switch()) {
1069 force_routing = true;
1070 force_restart_session = true;
1071 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301072 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1073
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001075 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001076 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1078 switch_device[i] = false;
1079
1080 list_for_each(node, &adev->usecase_list) {
1081 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001082
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301083 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1084 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301085 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301086 platform_get_snd_device_name(usecase->out_snd_device),
1087 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001088 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301089 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001090 (derive_playback_snd_device(adev->platform,
1091 usecase, uc_info,
1092 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301093 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1094 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301095 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301096 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1097 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1098 ((force_restart_session) ||
1099 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301100
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301101 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1102 __func__, use_case_table[usecase->id],
1103 platform_get_snd_device_name(usecase->out_snd_device));
1104 disable_audio_route(adev, usecase);
1105 switch_device[usecase->id] = true;
1106 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 }
1108 }
1109
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301110 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1111 num_uc_to_switch);
1112
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001114 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301116 /* Make sure the previous devices to be disabled first and then enable the
1117 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118 list_for_each(node, &adev->usecase_list) {
1119 usecase = node_to_item(node, struct audio_usecase, list);
1120 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001121 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 }
1123 }
1124
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001125 list_for_each(node, &adev->usecase_list) {
1126 usecase = node_to_item(node, struct audio_usecase, list);
1127 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001128 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001129 }
1130 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 /* Re-route all the usecases on the shared backend other than the
1133 specified usecase to new snd devices */
1134 list_for_each(node, &adev->usecase_list) {
1135 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301136 /* Update the out_snd_device only before enabling the audio route */
1137 if (switch_device[usecase->id]) {
1138 usecase->out_snd_device = snd_device;
1139 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301140 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301141 use_case_table[usecase->id],
1142 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001143 /* Update voc calibration before enabling VoIP route */
1144 if (usecase->type == VOIP_CALL)
1145 status = platform_switch_voice_call_device_post(adev->platform,
1146 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001147 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301148 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301149 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 }
1151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 }
1153}
1154
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301155static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001156 struct audio_usecase *uc_info,
1157 snd_device_t snd_device)
1158{
1159 struct listnode *node;
1160 struct audio_usecase *usecase;
1161 bool switch_device[AUDIO_USECASE_MAX];
1162 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301163 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001164 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301166 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1167 snd_device);
1168 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301169
1170 /*
1171 * Make sure out devices is checked against out codec backend device and
1172 * also in devices against in codec backend. Checking out device against in
1173 * codec backend or vice versa causes issues.
1174 */
1175 if (uc_info->type == PCM_CAPTURE)
1176 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177 /*
1178 * This function is to make sure that all the active capture usecases
1179 * are always routed to the same input sound device.
1180 * For example, if audio-record and voice-call usecases are currently
1181 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1182 * is received for voice call then we have to make sure that audio-record
1183 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1184 * because of the limitation that two devices cannot be enabled
1185 * at the same time if they share the same backend.
1186 */
1187 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1188 switch_device[i] = false;
1189
1190 list_for_each(node, &adev->usecase_list) {
1191 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301192 /*
1193 * TODO: Enhance below condition to handle BT sco/USB multi recording
1194 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001195 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001196 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301197 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301198 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301199 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001200 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001201 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001202 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1203 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001204 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001205 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001206 switch_device[usecase->id] = true;
1207 num_uc_to_switch++;
1208 }
1209 }
1210
1211 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001212 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301214 /* Make sure the previous devices to be disabled first and then enable the
1215 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216 list_for_each(node, &adev->usecase_list) {
1217 usecase = node_to_item(node, struct audio_usecase, list);
1218 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001219 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001220 }
1221 }
1222
1223 list_for_each(node, &adev->usecase_list) {
1224 usecase = node_to_item(node, struct audio_usecase, list);
1225 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001226 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001227 }
1228 }
1229
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 /* Re-route all the usecases on the shared backend other than the
1231 specified usecase to new snd devices */
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 /* Update the in_snd_device only before enabling the audio route */
1235 if (switch_device[usecase->id] ) {
1236 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001237 if (usecase->type != VOICE_CALL) {
1238 /* Update voc calibration before enabling VoIP route */
1239 if (usecase->type == VOIP_CALL)
1240 status = platform_switch_voice_call_device_post(adev->platform,
1241 usecase->out_snd_device,
1242 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301243 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001244 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001245 }
1246 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001247 }
1248}
1249
Mingming Yin3a941d42016-02-17 18:08:05 -08001250static void reset_hdmi_sink_caps(struct stream_out *out) {
1251 int i = 0;
1252
1253 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1254 out->supported_channel_masks[i] = 0;
1255 }
1256 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1257 out->supported_formats[i] = 0;
1258 }
1259 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1260 out->supported_sample_rates[i] = 0;
1261 }
1262}
1263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001265static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266{
Mingming Yin3a941d42016-02-17 18:08:05 -08001267 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001268 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269
Mingming Yin3a941d42016-02-17 18:08:05 -08001270 reset_hdmi_sink_caps(out);
1271
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001272 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001273 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001274 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001275 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001276 }
1277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001280 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001281 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001282 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1283 case 6:
1284 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1285 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1286 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1287 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 break;
1291 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001292 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001293 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294 break;
1295 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001296
1297 // check channel format caps
1298 i = 0;
1299 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1300 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1301 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1302 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1303 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1304 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1305 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1306 }
1307
1308 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1309 ALOGV(":%s HDMI supports DTS format", __func__);
1310 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1311 }
1312
1313 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1314 ALOGV(":%s HDMI supports DTS HD format", __func__);
1315 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1316 }
1317
1318
1319 // check sample rate caps
1320 i = 0;
1321 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1322 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1323 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1324 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1325 }
1326 }
1327
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001328 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329}
1330
Alexy Josephb1379942016-01-29 15:49:38 -08001331audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001332 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001333{
1334 struct audio_usecase *usecase;
1335 struct listnode *node;
1336
1337 list_for_each(node, &adev->usecase_list) {
1338 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001339 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001340 ALOGV("%s: usecase id %d", __func__, usecase->id);
1341 return usecase->id;
1342 }
1343 }
1344 return USECASE_INVALID;
1345}
1346
Alexy Josephb1379942016-01-29 15:49:38 -08001347struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001348 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001349{
1350 struct audio_usecase *usecase;
1351 struct listnode *node;
1352
1353 list_for_each(node, &adev->usecase_list) {
1354 usecase = node_to_item(node, struct audio_usecase, list);
1355 if (usecase->id == uc_id)
1356 return usecase;
1357 }
1358 return NULL;
1359}
1360
Dhananjay Kumard4833242016-10-06 22:09:12 +05301361struct stream_in *get_next_active_input(const struct audio_device *adev)
1362{
1363 struct audio_usecase *usecase;
1364 struct listnode *node;
1365
1366 list_for_each_reverse(node, &adev->usecase_list) {
1367 usecase = node_to_item(node, struct audio_usecase, list);
1368 if (usecase->type == PCM_CAPTURE)
1369 return usecase->stream.in;
1370 }
1371 return NULL;
1372}
1373
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301374/*
1375 * is a true native playback active
1376 */
1377bool audio_is_true_native_stream_active(struct audio_device *adev)
1378{
1379 bool active = false;
1380 int i = 0;
1381 struct listnode *node;
1382
1383 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1384 ALOGV("%s:napb: not in true mode or non hdphones device",
1385 __func__);
1386 active = false;
1387 goto exit;
1388 }
1389
1390 list_for_each(node, &adev->usecase_list) {
1391 struct audio_usecase *uc;
1392 uc = node_to_item(node, struct audio_usecase, list);
1393 struct stream_out *curr_out =
1394 (struct stream_out*) uc->stream.out;
1395
1396 if (curr_out && PCM_PLAYBACK == uc->type) {
1397 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1398 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1399 uc->id, curr_out->sample_rate,
1400 curr_out->bit_width,
1401 platform_get_snd_device_name(uc->out_snd_device));
1402
1403 if (is_offload_usecase(uc->id) &&
1404 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1405 active = true;
1406 ALOGD("%s:napb:native stream detected", __func__);
1407 }
1408 }
1409 }
1410exit:
1411 return active;
1412}
1413
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301414/*
1415 * if native DSD playback active
1416 */
1417bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1418{
1419 bool active = false;
1420 struct listnode *node = NULL;
1421 struct audio_usecase *uc = NULL;
1422 struct stream_out *curr_out = NULL;
1423
1424 list_for_each(node, &adev->usecase_list) {
1425 uc = node_to_item(node, struct audio_usecase, list);
1426 curr_out = (struct stream_out*) uc->stream.out;
1427
1428 if (curr_out && PCM_PLAYBACK == uc->type &&
1429 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1430 active = true;
1431 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301432 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301433 }
1434 }
1435 return active;
1436}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301437
1438static bool force_device_switch(struct audio_usecase *usecase)
1439{
1440 bool ret = false;
1441 bool is_it_true_mode = false;
1442
1443 if (is_offload_usecase(usecase->id) &&
1444 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001445 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1446 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1447 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301448 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1449 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1450 (!is_it_true_mode && adev->native_playback_enabled)){
1451 ret = true;
1452 ALOGD("napb: time to toggle native mode");
1453 }
1454 }
1455
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301456 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301457 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1458 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301459 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001460 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301461 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301462 ALOGD("Force a2dp device switch to update new encoder config");
1463 ret = true;
1464 }
1465
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301466 return ret;
1467}
1468
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001469int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001471 snd_device_t out_snd_device = SND_DEVICE_NONE;
1472 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 struct audio_usecase *usecase = NULL;
1474 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001475 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001476 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001477 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301480 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1481
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 usecase = get_usecase_from_list(adev, uc_id);
1483 if (usecase == NULL) {
1484 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1485 return -EINVAL;
1486 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001488 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001489 (usecase->type == VOIP_CALL) ||
1490 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301491 if(usecase->stream.out == NULL) {
1492 ALOGE("%s: stream.out is NULL", __func__);
1493 return -EINVAL;
1494 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001495 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001496 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001497 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498 usecase->devices = usecase->stream.out->devices;
1499 } else {
1500 /*
1501 * If the voice call is active, use the sound devices of voice call usecase
1502 * so that it would not result any device switch. All the usecases will
1503 * be switched to new device when select_devices() is called for voice call
1504 * usecase. This is to avoid switching devices for voice call when
1505 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001506 * choose voice call device only if the use case device is
1507 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001509 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001510 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001511 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001512 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1513 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301514 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1515 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001516 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 in_snd_device = vc_usecase->in_snd_device;
1518 out_snd_device = vc_usecase->out_snd_device;
1519 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001520 } else if (voice_extn_compress_voip_is_active(adev)) {
1521 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001522 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001523 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1524 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001525 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001526 in_snd_device = voip_usecase->in_snd_device;
1527 out_snd_device = voip_usecase->out_snd_device;
1528 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001529 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001530 hfp_ucid = audio_extn_hfp_get_usecase();
1531 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001532 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001533 in_snd_device = hfp_usecase->in_snd_device;
1534 out_snd_device = hfp_usecase->out_snd_device;
1535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 }
1537 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301538 if (usecase->stream.out == NULL) {
1539 ALOGE("%s: stream.out is NULL", __func__);
1540 return -EINVAL;
1541 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542 usecase->devices = usecase->stream.out->devices;
1543 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001544 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001545 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001546 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001547 if (usecase->stream.out == adev->primary_output &&
1548 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001549 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001550 select_devices(adev, adev->active_input->usecase);
1551 }
1552 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301554 if (usecase->stream.in == NULL) {
1555 ALOGE("%s: stream.in is NULL", __func__);
1556 return -EINVAL;
1557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 usecase->devices = usecase->stream.in->device;
1559 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001560 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001561 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001562 if (adev->active_input &&
1563 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301564 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1565 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1566 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001567 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001568 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001569 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1570 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001571 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001572 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574 }
1575 }
1576
1577 if (out_snd_device == usecase->out_snd_device &&
1578 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301579
1580 if (!force_device_switch(usecase))
1581 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
sangwoobc677242013-08-08 16:53:43 +09001584 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001585 out_snd_device, platform_get_snd_device_name(out_snd_device),
1586 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588 /*
1589 * Limitation: While in call, to do a device switch we need to disable
1590 * and enable both RX and TX devices though one of them is same as current
1591 * device.
1592 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001593 if ((usecase->type == VOICE_CALL) &&
1594 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1595 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001596 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001597 }
1598
1599 if (((usecase->type == VOICE_CALL) ||
1600 (usecase->type == VOIP_CALL)) &&
1601 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1602 /* Disable sidetone only if voice/voip call already exists */
1603 if (voice_is_call_state_active(adev) ||
1604 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001605 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001606
1607 /* Disable aanc only if voice call exists */
1608 if (voice_is_call_state_active(adev))
1609 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001610 }
1611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001612 /* Disable current sound devices */
1613 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001614 disable_audio_route(adev, usecase);
1615 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 }
1617
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001618 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001619 disable_audio_route(adev, usecase);
1620 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 }
1622
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001623 /* Applicable only on the targets that has external modem.
1624 * New device information should be sent to modem before enabling
1625 * the devices to reduce in-call device switch time.
1626 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001627 if ((usecase->type == VOICE_CALL) &&
1628 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1629 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001630 status = platform_switch_voice_call_enable_device_config(adev->platform,
1631 out_snd_device,
1632 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001633 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001634
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001635 /* Enable new sound devices */
1636 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001637 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301638 if (platform_check_codec_asrc_support(adev->platform))
1639 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001640 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641 }
1642
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001643 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301644 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001645 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001646 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647
Avinash Vaish71a8b972014-07-24 15:36:33 +05301648 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001649 status = platform_switch_voice_call_device_post(adev->platform,
1650 out_snd_device,
1651 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301652 enable_audio_route_for_voice_usecases(adev, usecase);
1653 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001654
sangwoo170731f2013-06-08 15:36:36 +09001655 usecase->in_snd_device = in_snd_device;
1656 usecase->out_snd_device = out_snd_device;
1657
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301658 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1659 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301660 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001661 if ((24 == usecase->stream.out->bit_width) &&
1662 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1663 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1664 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1665 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1666 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1667 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1668 /*
1669 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1670 * configured device sample rate, if not update the COPP rate to be equal to the
1671 * device sample rate, else open COPP at stream sample rate
1672 */
1673 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1674 usecase->stream.out->sample_rate,
1675 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301676 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1677 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001678 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1679 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1680 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1681 }
1682
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001683 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001684 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001685 audio_extn_gef_notify_device_config(
1686 usecase->stream.out->devices,
1687 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001688 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001689 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001690 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301691 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001692 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001693
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001694 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001695 /* Enable aanc only if voice call exists */
1696 if (voice_is_call_state_active(adev))
1697 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1698
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001699 /* Enable sidetone only if other voice/voip call already exists */
1700 if (voice_is_call_state_active(adev) ||
1701 voice_extn_compress_voip_is_started(adev))
1702 voice_set_sidetone(adev, out_snd_device, true);
1703 }
1704
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001705 /* Applicable only on the targets that has external modem.
1706 * Enable device command should be sent to modem only after
1707 * enabling voice call mixer controls
1708 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001709 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001710 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1711 out_snd_device,
1712 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301713 ALOGD("%s: done",__func__);
1714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715 return status;
1716}
1717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718static int stop_input_stream(struct stream_in *in)
1719{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301720 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721 struct audio_usecase *uc_info;
1722 struct audio_device *adev = in->dev;
1723
Eric Laurent994a6932013-07-17 11:51:42 -07001724 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726 uc_info = get_usecase_from_list(adev, in->usecase);
1727 if (uc_info == NULL) {
1728 ALOGE("%s: Could not find the usecase (%d) in the list",
1729 __func__, in->usecase);
1730 return -EINVAL;
1731 }
1732
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001733 /* Close in-call recording streams */
1734 voice_check_and_stop_incall_rec_usecase(adev, in);
1735
Eric Laurent150dbfe2013-02-27 14:31:02 -08001736 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001737 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001738
1739 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001740 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001742 list_remove(&uc_info->list);
1743 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001745 adev->active_input = get_next_active_input(adev);
1746
Eric Laurent994a6932013-07-17 11:51:42 -07001747 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 return ret;
1749}
1750
1751int start_input_stream(struct stream_in *in)
1752{
1753 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001754 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 struct audio_usecase *uc_info;
1756 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301757 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758
Mingming Yin2664a5b2015-09-03 10:53:11 -07001759 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1760 if (get_usecase_from_list(adev, usecase) == NULL)
1761 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301762 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1763 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001764
Naresh Tanniru80659832014-06-04 18:17:56 +05301765
1766 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301767 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301768 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301769 goto error_config;
1770 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301771
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001772 /* Check if source matches incall recording usecase criteria */
1773 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1774 if (ret)
1775 goto error_config;
1776 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001777 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1778
1779 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1780 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1781 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001782 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001783 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001784
Eric Laurentb23d5282013-05-14 15:27:20 -07001785 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 if (in->pcm_device_id < 0) {
1787 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1788 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001789 ret = -EINVAL;
1790 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001792
1793 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001795
1796 if (!uc_info) {
1797 ret = -ENOMEM;
1798 goto error_config;
1799 }
1800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 uc_info->id = in->usecase;
1802 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001803 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001804 uc_info->devices = in->device;
1805 uc_info->in_snd_device = SND_DEVICE_NONE;
1806 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001808 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301809 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1810 adev->perf_lock_opts,
1811 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001812 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301814 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1815 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001816
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301817 if (audio_extn_cin_attached_usecase(in->usecase)) {
1818 ret = audio_extn_cin_start_input_stream(in);
1819 if (ret)
1820 goto error_open;
1821 else
1822 goto done_open;
1823 }
1824
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001825 unsigned int flags = PCM_IN;
1826 unsigned int pcm_open_retry_count = 0;
1827
1828 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1829 flags |= PCM_MMAP | PCM_NOIRQ;
1830 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001831 } else if (in->realtime) {
1832 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001833 }
1834
1835 while (1) {
1836 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1837 flags, &in->config);
1838 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1839 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1840 if (in->pcm != NULL) {
1841 pcm_close(in->pcm);
1842 in->pcm = NULL;
1843 }
1844 if (pcm_open_retry_count-- == 0) {
1845 ret = -EIO;
1846 goto error_open;
1847 }
1848 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1849 continue;
1850 }
1851 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001853
1854 ALOGV("%s: pcm_prepare", __func__);
1855 ret = pcm_prepare(in->pcm);
1856 if (ret < 0) {
1857 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1858 pcm_close(in->pcm);
1859 in->pcm = NULL;
1860 goto error_open;
1861 }
1862
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001863 register_in_stream(in);
1864 if (in->realtime) {
1865 ret = pcm_start(in->pcm);
1866 if (ret < 0)
1867 goto error_open;
1868 }
1869
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301870done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301871 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001872 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001873
Eric Laurentc8400632013-02-14 19:04:54 -08001874 return ret;
1875
1876error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301877 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001879error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301880 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301881 /*
1882 * sleep 50ms to allow sufficient time for kernel
1883 * drivers to recover incases like SSR.
1884 */
1885 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001887
1888 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889}
1890
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001891void lock_input_stream(struct stream_in *in)
1892{
1893 pthread_mutex_lock(&in->pre_lock);
1894 pthread_mutex_lock(&in->lock);
1895 pthread_mutex_unlock(&in->pre_lock);
1896}
1897
1898void lock_output_stream(struct stream_out *out)
1899{
1900 pthread_mutex_lock(&out->pre_lock);
1901 pthread_mutex_lock(&out->lock);
1902 pthread_mutex_unlock(&out->pre_lock);
1903}
1904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001905/* must be called with out->lock locked */
1906static int send_offload_cmd_l(struct stream_out* out, int command)
1907{
1908 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1909
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001910 if (!cmd) {
1911 ALOGE("failed to allocate mem for command 0x%x", command);
1912 return -ENOMEM;
1913 }
1914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001915 ALOGVV("%s %d", __func__, command);
1916
1917 cmd->cmd = command;
1918 list_add_tail(&out->offload_cmd_list, &cmd->node);
1919 pthread_cond_signal(&out->offload_cond);
1920 return 0;
1921}
1922
1923/* must be called iwth out->lock locked */
1924static void stop_compressed_output_l(struct stream_out *out)
1925{
1926 out->offload_state = OFFLOAD_STATE_IDLE;
1927 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001928 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929 if (out->compr != NULL) {
1930 compress_stop(out->compr);
1931 while (out->offload_thread_blocked) {
1932 pthread_cond_wait(&out->cond, &out->lock);
1933 }
1934 }
1935}
1936
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001937bool is_offload_usecase(audio_usecase_t uc_id)
1938{
1939 unsigned int i;
1940 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1941 if (uc_id == offload_usecases[i])
1942 return true;
1943 }
1944 return false;
1945}
1946
vivek mehta446c3962015-09-14 10:57:35 -07001947static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001948{
vivek mehta446c3962015-09-14 10:57:35 -07001949 audio_usecase_t ret_uc = USECASE_INVALID;
1950 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001951 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001952 if (!adev->multi_offload_enable) {
1953 if (is_direct_pcm)
1954 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1955 else
1956 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001957
vivek mehta446c3962015-09-14 10:57:35 -07001958 pthread_mutex_lock(&adev->lock);
1959 if (get_usecase_from_list(adev, ret_uc) != NULL)
1960 ret_uc = USECASE_INVALID;
1961 pthread_mutex_unlock(&adev->lock);
1962
1963 return ret_uc;
1964 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001965
1966 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001967 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1968 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1969 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1970 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001971 break;
1972 }
1973 }
vivek mehta446c3962015-09-14 10:57:35 -07001974
1975 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1976 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001977}
1978
1979static void free_offload_usecase(struct audio_device *adev,
1980 audio_usecase_t uc_id)
1981{
vivek mehta446c3962015-09-14 10:57:35 -07001982 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001983 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001984
1985 if (!adev->multi_offload_enable)
1986 return;
1987
1988 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1989 if (offload_usecases[offload_uc_index] == uc_id) {
1990 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001991 break;
1992 }
1993 }
1994 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1995}
1996
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997static void *offload_thread_loop(void *context)
1998{
1999 struct stream_out *out = (struct stream_out *) context;
2000 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002001 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2004 set_sched_policy(0, SP_FOREGROUND);
2005 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2006
2007 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002008 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 for (;;) {
2010 struct offload_cmd *cmd = NULL;
2011 stream_callback_event_t event;
2012 bool send_callback = false;
2013
2014 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2015 __func__, list_empty(&out->offload_cmd_list),
2016 out->offload_state);
2017 if (list_empty(&out->offload_cmd_list)) {
2018 ALOGV("%s SLEEPING", __func__);
2019 pthread_cond_wait(&out->offload_cond, &out->lock);
2020 ALOGV("%s RUNNING", __func__);
2021 continue;
2022 }
2023
2024 item = list_head(&out->offload_cmd_list);
2025 cmd = node_to_item(item, struct offload_cmd, node);
2026 list_remove(item);
2027
2028 ALOGVV("%s STATE %d CMD %d out->compr %p",
2029 __func__, out->offload_state, cmd->cmd, out->compr);
2030
2031 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2032 free(cmd);
2033 break;
2034 }
2035
2036 if (out->compr == NULL) {
2037 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002038 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 pthread_cond_signal(&out->cond);
2040 continue;
2041 }
2042 out->offload_thread_blocked = true;
2043 pthread_mutex_unlock(&out->lock);
2044 send_callback = false;
2045 switch(cmd->cmd) {
2046 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002047 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002049 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050 send_callback = true;
2051 event = STREAM_CBK_EVENT_WRITE_READY;
2052 break;
2053 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002054 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302055 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002056 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302057 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002058 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302059 if (ret < 0)
2060 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302061 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302062 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002063 compress_drain(out->compr);
2064 else
2065 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302066 if (ret != -ENETRESET) {
2067 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302068 pthread_mutex_lock(&out->lock);
2069 out->send_new_metadata = 1;
2070 out->send_next_track_params = true;
2071 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302072 event = STREAM_CBK_EVENT_DRAIN_READY;
2073 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2074 } else
2075 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 break;
2077 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002078 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002080 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002081 send_callback = true;
2082 event = STREAM_CBK_EVENT_DRAIN_READY;
2083 break;
2084 default:
2085 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2086 break;
2087 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002088 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 out->offload_thread_blocked = false;
2090 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002091 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002092 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002094 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 free(cmd);
2096 }
2097
2098 pthread_cond_signal(&out->cond);
2099 while (!list_empty(&out->offload_cmd_list)) {
2100 item = list_head(&out->offload_cmd_list);
2101 list_remove(item);
2102 free(node_to_item(item, struct offload_cmd, node));
2103 }
2104 pthread_mutex_unlock(&out->lock);
2105
2106 return NULL;
2107}
2108
2109static int create_offload_callback_thread(struct stream_out *out)
2110{
2111 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2112 list_init(&out->offload_cmd_list);
2113 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2114 offload_thread_loop, out);
2115 return 0;
2116}
2117
2118static int destroy_offload_callback_thread(struct stream_out *out)
2119{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002120 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 stop_compressed_output_l(out);
2122 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2123
2124 pthread_mutex_unlock(&out->lock);
2125 pthread_join(out->offload_thread, (void **) NULL);
2126 pthread_cond_destroy(&out->offload_cond);
2127
2128 return 0;
2129}
2130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131static int stop_output_stream(struct stream_out *out)
2132{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302133 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134 struct audio_usecase *uc_info;
2135 struct audio_device *adev = out->dev;
2136
Eric Laurent994a6932013-07-17 11:51:42 -07002137 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002138 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 uc_info = get_usecase_from_list(adev, out->usecase);
2140 if (uc_info == NULL) {
2141 ALOGE("%s: Could not find the usecase (%d) in the list",
2142 __func__, out->usecase);
2143 return -EINVAL;
2144 }
2145
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002146 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302147 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002148 if (adev->visualizer_stop_output != NULL)
2149 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002150
2151 audio_extn_dts_remove_state_notifier_node(out->usecase);
2152
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002153 if (adev->offload_effects_stop_output != NULL)
2154 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2155 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002156
Eric Laurent150dbfe2013-02-27 14:31:02 -08002157 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002158 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002159
2160 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002161 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002163 list_remove(&uc_info->list);
2164 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002166 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302167 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002168 ALOGV("Disable passthrough , reset mixer to pcm");
2169 /* NO_PASSTHROUGH */
2170 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002171 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002172 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2173 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002174
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302175 /* Must be called after removing the usecase from list */
2176 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302177 audio_extn_keep_alive_start();
2178
Eric Laurent994a6932013-07-17 11:51:42 -07002179 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 return ret;
2181}
2182
2183int start_output_stream(struct stream_out *out)
2184{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 struct audio_usecase *uc_info;
2187 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302188 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002189 char mixer_ctl_name[128];
2190 struct mixer_ctl *ctl = NULL;
2191 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002193 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2194 ret = -EINVAL;
2195 goto error_config;
2196 }
2197
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302198 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2199 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2200 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302201
Naresh Tanniru80659832014-06-04 18:17:56 +05302202 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302203 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302204 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302205 goto error_config;
2206 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302207
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302208 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2209 if (!audio_extn_a2dp_is_ready()) {
2210 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2211 //combo usecase just by pass a2dp
2212 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2213 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2214 } else {
2215 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2216 ret = -EAGAIN;
2217 goto error_config;
2218 }
2219 }
2220 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002221 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 if (out->pcm_device_id < 0) {
2223 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2224 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002225 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002226 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 }
2228
2229 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002230
2231 if (!uc_info) {
2232 ret = -ENOMEM;
2233 goto error_config;
2234 }
2235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 uc_info->id = out->usecase;
2237 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002238 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002239 uc_info->devices = out->devices;
2240 uc_info->in_snd_device = SND_DEVICE_NONE;
2241 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002242 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302244 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2245 adev->perf_lock_opts,
2246 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302247
2248 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2249 audio_extn_keep_alive_stop();
2250 if (audio_extn_passthru_is_enabled() &&
2251 audio_extn_passthru_is_passthrough_stream(out)) {
2252 audio_extn_passthru_on_start(out);
2253 audio_extn_passthru_update_stream_configuration(adev, out);
2254 }
2255 }
2256
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 select_devices(adev, out->usecase);
2258
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002259 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2260 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002261 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002262 unsigned int flags = PCM_OUT;
2263 unsigned int pcm_open_retry_count = 0;
2264 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2265 flags |= PCM_MMAP | PCM_NOIRQ;
2266 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002267 } else if (out->realtime) {
2268 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002269 } else
2270 flags |= PCM_MONOTONIC;
2271
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002272 if ((adev->vr_audio_mode_enabled) &&
2273 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2274 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2275 "PCM_Dev %d Topology", out->pcm_device_id);
2276 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2277 if (!ctl) {
2278 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2279 __func__, mixer_ctl_name);
2280 } else {
2281 //if success use ULLPP
2282 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2283 __func__, mixer_ctl_name, out->pcm_device_id);
2284 //There is a still a possibility that some sessions
2285 // that request for FAST|RAW when 3D audio is active
2286 //can go through ULLPP. Ideally we expects apps to
2287 //listen to audio focus and stop concurrent playback
2288 //Also, we will look for mode flag (voice_in_communication)
2289 //before enabling the realtime flag.
2290 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2291 }
2292 }
2293
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002294 while (1) {
2295 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2296 flags, &out->config);
2297 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2298 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2299 if (out->pcm != NULL) {
2300 pcm_close(out->pcm);
2301 out->pcm = NULL;
2302 }
2303 if (pcm_open_retry_count-- == 0) {
2304 ret = -EIO;
2305 goto error_open;
2306 }
2307 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2308 continue;
2309 }
2310 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002311 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002312
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002313 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2314 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002315
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002316 ALOGV("%s: pcm_prepare", __func__);
2317 if (pcm_is_ready(out->pcm)) {
2318 ret = pcm_prepare(out->pcm);
2319 if (ret < 0) {
2320 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2321 pcm_close(out->pcm);
2322 out->pcm = NULL;
2323 goto error_open;
2324 }
2325 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002326 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002327 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2328 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002330 out->compr = compress_open(adev->snd_card,
2331 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 COMPRESS_IN, &out->compr_config);
2333 if (out->compr && !is_compress_ready(out->compr)) {
2334 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2335 compress_close(out->compr);
2336 out->compr = NULL;
2337 ret = -EIO;
2338 goto error_open;
2339 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302340 /* compress_open sends params of the track, so reset the flag here */
2341 out->is_compr_metadata_avail = false;
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 if (out->offload_callback)
2344 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002345
Fred Oh3f43e742015-03-04 18:42:34 -08002346 /* Since small bufs uses blocking writes, a write will be blocked
2347 for the default max poll time (20s) in the event of an SSR.
2348 Reduce the poll time to observe and deal with SSR faster.
2349 */
Ashish Jain5106d362016-05-11 19:23:33 +05302350 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002351 compress_set_max_poll_wait(out->compr, 1000);
2352 }
2353
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002354 audio_extn_dts_create_state_notifier_node(out->usecase);
2355 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2356 popcount(out->channel_mask),
2357 out->playback_started);
2358
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002359#ifdef DS1_DOLBY_DDP_ENABLED
2360 if (audio_extn_is_dolby_format(out->format))
2361 audio_extn_dolby_send_ddp_endp_params(adev);
2362#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302363 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2364 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002365 if (adev->visualizer_start_output != NULL)
2366 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2367 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302368 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002369 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002370 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002372
2373 if (ret == 0) {
2374 register_out_stream(out);
2375 if (out->realtime) {
2376 ret = pcm_start(out->pcm);
2377 if (ret < 0)
2378 goto error_open;
2379 }
2380 }
2381
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302382 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002383 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002384
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002385 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302387 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002389error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302390 /*
2391 * sleep 50ms to allow sufficient time for kernel
2392 * drivers to recover incases like SSR.
2393 */
2394 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002395 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396}
2397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398static int check_input_parameters(uint32_t sample_rate,
2399 audio_format_t format,
2400 int channel_count)
2401{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002402 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302404 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2405 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2406 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002407 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302408 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002409
2410 switch (channel_count) {
2411 case 1:
2412 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302413 case 3:
2414 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002415 case 6:
2416 break;
2417 default:
2418 ret = -EINVAL;
2419 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420
2421 switch (sample_rate) {
2422 case 8000:
2423 case 11025:
2424 case 12000:
2425 case 16000:
2426 case 22050:
2427 case 24000:
2428 case 32000:
2429 case 44100:
2430 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302431 case 96000:
2432 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433 break;
2434 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002435 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 }
2437
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002438 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439}
2440
2441static size_t get_input_buffer_size(uint32_t sample_rate,
2442 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002443 int channel_count,
2444 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445{
2446 size_t size = 0;
2447
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002448 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2449 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002451 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002452 if (is_low_latency)
2453 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302454
2455 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002457 /* make sure the size is multiple of 32 bytes
2458 * At 48 kHz mono 16-bit PCM:
2459 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2460 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2461 */
2462 size += 0x1f;
2463 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002464
2465 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466}
2467
Ashish Jain058165c2016-09-28 23:18:48 +05302468static size_t get_output_period_size(uint32_t sample_rate,
2469 audio_format_t format,
2470 int channel_count,
2471 int duration /*in millisecs*/)
2472{
2473 size_t size = 0;
2474 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2475
2476 if ((duration == 0) || (sample_rate == 0) ||
2477 (bytes_per_sample == 0) || (channel_count == 0)) {
2478 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2479 bytes_per_sample, channel_count);
2480 return -EINVAL;
2481 }
2482
2483 size = (sample_rate *
2484 duration *
2485 bytes_per_sample *
2486 channel_count) / 1000;
2487 /*
2488 * To have same PCM samples for all channels, the buffer size requires to
2489 * be multiple of (number of channels * bytes per sample)
2490 * For writes to succeed, the buffer must be written at address which is multiple of 32
2491 */
2492 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2493
2494 return (size/(channel_count * bytes_per_sample));
2495}
2496
Ashish Jain5106d362016-05-11 19:23:33 +05302497static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2498{
2499 uint64_t actual_frames_rendered = 0;
2500 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2501
2502 /* This adjustment accounts for buffering after app processor.
2503 * It is based on estimated DSP latency per use case, rather than exact.
2504 */
2505 int64_t platform_latency = platform_render_latency(out->usecase) *
2506 out->sample_rate / 1000000LL;
2507
2508 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2509 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2510 * hence only estimate.
2511 */
2512 int64_t signed_frames = out->written - kernel_buffer_size;
2513
2514 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2515
2516 if (signed_frames > 0)
2517 actual_frames_rendered = signed_frames;
2518
2519 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2520 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2521 (long long int)out->written, (int)kernel_buffer_size,
2522 audio_bytes_per_sample(out->compr_config.codec->format),
2523 popcount(out->channel_mask));
2524
2525 return actual_frames_rendered;
2526}
2527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2529{
2530 struct stream_out *out = (struct stream_out *)stream;
2531
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533}
2534
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002535static int out_set_sample_rate(struct audio_stream *stream __unused,
2536 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537{
2538 return -ENOSYS;
2539}
2540
2541static size_t out_get_buffer_size(const struct audio_stream *stream)
2542{
2543 struct stream_out *out = (struct stream_out *)stream;
2544
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002545 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002547 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2548 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302549 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302550 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002552 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002553 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554}
2555
2556static uint32_t out_get_channels(const struct audio_stream *stream)
2557{
2558 struct stream_out *out = (struct stream_out *)stream;
2559
2560 return out->channel_mask;
2561}
2562
2563static audio_format_t out_get_format(const struct audio_stream *stream)
2564{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002565 struct stream_out *out = (struct stream_out *)stream;
2566
2567 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568}
2569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002570static int out_set_format(struct audio_stream *stream __unused,
2571 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572{
2573 return -ENOSYS;
2574}
2575
2576static int out_standby(struct audio_stream *stream)
2577{
2578 struct stream_out *out = (struct stream_out *)stream;
2579 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002580
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302581 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2582 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002584 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002586 if (adev->adm_deregister_stream)
2587 adev->adm_deregister_stream(adev->adm_data, out->handle);
2588
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002589 if (is_offload_usecase(out->usecase))
2590 stop_compressed_output_l(out);
2591
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002592 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002594 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2595 voice_extn_compress_voip_close_output_stream(stream);
2596 pthread_mutex_unlock(&adev->lock);
2597 pthread_mutex_unlock(&out->lock);
2598 ALOGD("VOIP output entered standby");
2599 return 0;
2600 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002601 if (out->pcm) {
2602 pcm_close(out->pcm);
2603 out->pcm = NULL;
2604 }
2605 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002606 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302607 out->send_next_track_params = false;
2608 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002609 out->gapless_mdata.encoder_delay = 0;
2610 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611 if (out->compr != NULL) {
2612 compress_close(out->compr);
2613 out->compr = NULL;
2614 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002617 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 }
2619 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302620 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 return 0;
2622}
2623
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002624static int out_dump(const struct audio_stream *stream __unused,
2625 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626{
2627 return 0;
2628}
2629
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002630static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2631{
2632 int ret = 0;
2633 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002634
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002635 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002636 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002637 return -EINVAL;
2638 }
2639
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302640 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002641
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002642 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2643 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302644 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002645 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002646 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2647 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302648 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002649 }
2650
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002651 ALOGV("%s new encoder delay %u and padding %u", __func__,
2652 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2653
2654 return 0;
2655}
2656
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002657static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2658{
2659 return out == adev->primary_output || out == adev->voice_tx_output;
2660}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2663{
2664 struct stream_out *out = (struct stream_out *)stream;
2665 struct audio_device *adev = out->dev;
2666 struct str_parms *parms;
2667 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002668 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669
sangwoobc677242013-08-08 16:53:43 +09002670 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002671 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302673 if (!parms)
2674 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002675 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2676 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002678 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002679 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002682 * When HDMI cable is unplugged the music playback is paused and
2683 * the policy manager sends routing=0. But the audioflinger continues
2684 * to write data until standby time (3sec). As the HDMI core is
2685 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002686 * Avoid this by routing audio to speaker until standby.
2687 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002688 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2689 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302690 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002691 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2692 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002693 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302694 /*
2695 * When A2DP is disconnected the
2696 * music playback is paused and the policy manager sends routing=0
2697 * But the audioflingercontinues to write data until standby time
2698 * (3sec). As BT is turned off, the write gets blocked.
2699 * Avoid this by routing audio to speaker until standby.
2700 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002701 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302702 (val == AUDIO_DEVICE_NONE)) {
2703 val = AUDIO_DEVICE_OUT_SPEAKER;
2704 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302705 /* To avoid a2dp to sco overlapping / BT device improper state
2706 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302707 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302708 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2709 if (!audio_extn_a2dp_is_ready()) {
2710 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2711 //combo usecase just by pass a2dp
2712 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2713 val = AUDIO_DEVICE_OUT_SPEAKER;
2714 } else {
2715 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2716 /* update device to a2dp and don't route as BT returned error
2717 * However it is still possible a2dp routing called because
2718 * of current active device disconnection (like wired headset)
2719 */
2720 out->devices = val;
2721 pthread_mutex_unlock(&out->lock);
2722 pthread_mutex_unlock(&adev->lock);
2723 goto error;
2724 }
2725 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302726 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 /*
2728 * select_devices() call below switches all the usecases on the same
2729 * backend to the new device. Refer to check_usecases_codec_backend() in
2730 * the select_devices(). But how do we undo this?
2731 *
2732 * For example, music playback is active on headset (deep-buffer usecase)
2733 * and if we go to ringtones and select a ringtone, low-latency usecase
2734 * will be started on headset+speaker. As we can't enable headset+speaker
2735 * and headset devices at the same time, select_devices() switches the music
2736 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2737 * So when the ringtone playback is completed, how do we undo the same?
2738 *
2739 * We are relying on the out_set_parameters() call on deep-buffer output,
2740 * once the ringtone playback is ended.
2741 * NOTE: We should not check if the current devices are same as new devices.
2742 * Because select_devices() must be called to switch back the music
2743 * playback to headset.
2744 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002745 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002746 audio_devices_t new_dev = val;
2747 bool same_dev = out->devices == new_dev;
2748 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002749
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002750 if (output_drives_call(adev, out)) {
2751 if(!voice_is_in_call(adev)) {
2752 if (adev->mode == AUDIO_MODE_IN_CALL) {
2753 adev->current_call_output = out;
2754 ret = voice_start_call(adev);
2755 }
2756 } else {
2757 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002758 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002759 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002760 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002761
2762 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002763 if (!same_dev) {
2764 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302765 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2766 adev->perf_lock_opts,
2767 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002768 if (adev->adm_on_routing_change)
2769 adev->adm_on_routing_change(adev->adm_data,
2770 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002771 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002772 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302773 if (!same_dev)
2774 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002775 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002776 }
2777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002779 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002781
2782 if (out == adev->primary_output) {
2783 pthread_mutex_lock(&adev->lock);
2784 audio_extn_set_parameters(adev, parms);
2785 pthread_mutex_unlock(&adev->lock);
2786 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002787 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002788 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002789 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002790
2791 audio_extn_dts_create_state_notifier_node(out->usecase);
2792 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2793 popcount(out->channel_mask),
2794 out->playback_started);
2795
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002796 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002797 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002798
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302799 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2800 if (err >= 0) {
2801 strlcpy(out->profile, value, sizeof(out->profile));
2802 ALOGV("updating stream profile with value '%s'", out->profile);
2803 lock_output_stream(out);
2804 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2805 &adev->streams_output_cfg_list,
2806 out->devices, out->flags, out->format,
2807 out->sample_rate, out->bit_width,
2808 out->channel_mask, out->profile,
2809 &out->app_type_cfg);
2810 pthread_mutex_unlock(&out->lock);
2811 }
2812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302814error:
Eric Laurent994a6932013-07-17 11:51:42 -07002815 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 return ret;
2817}
2818
2819static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2820{
2821 struct stream_out *out = (struct stream_out *)stream;
2822 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002823 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 char value[256];
2825 struct str_parms *reply = str_parms_create();
2826 size_t i, j;
2827 int ret;
2828 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002829
2830 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002831 if (reply) {
2832 str_parms_destroy(reply);
2833 }
2834 if (query) {
2835 str_parms_destroy(query);
2836 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002837 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2838 return NULL;
2839 }
2840
Eric Laurent994a6932013-07-17 11:51:42 -07002841 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2843 if (ret >= 0) {
2844 value[0] = '\0';
2845 i = 0;
2846 while (out->supported_channel_masks[i] != 0) {
2847 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2848 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2849 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002850 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002852 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 first = false;
2854 break;
2855 }
2856 }
2857 i++;
2858 }
2859 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2860 str = str_parms_to_str(reply);
2861 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002862 voice_extn_out_get_parameters(out, query, reply);
2863 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002864 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002865 free(str);
2866 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002867 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002869
Alexy Joseph62142aa2015-11-16 15:10:34 -08002870
2871 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2872 if (ret >= 0) {
2873 value[0] = '\0';
2874 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2875 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302876 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002877 } else {
2878 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302879 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002880 }
2881 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002882 if (str)
2883 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002884 str = str_parms_to_str(reply);
2885 }
2886
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002887 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2888 if (ret >= 0) {
2889 value[0] = '\0';
2890 i = 0;
2891 first = true;
2892 while (out->supported_formats[i] != 0) {
2893 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2894 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2895 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002896 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002897 }
2898 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2899 first = false;
2900 break;
2901 }
2902 }
2903 i++;
2904 }
2905 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002906 if (str)
2907 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002908 str = str_parms_to_str(reply);
2909 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002910
2911 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2912 if (ret >= 0) {
2913 value[0] = '\0';
2914 i = 0;
2915 first = true;
2916 while (out->supported_sample_rates[i] != 0) {
2917 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2918 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2919 if (!first) {
2920 strlcat(value, "|", sizeof(value));
2921 }
2922 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2923 first = false;
2924 break;
2925 }
2926 }
2927 i++;
2928 }
2929 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2930 if (str)
2931 free(str);
2932 str = str_parms_to_str(reply);
2933 }
2934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 str_parms_destroy(query);
2936 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002937 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 return str;
2939}
2940
2941static uint32_t out_get_latency(const struct audio_stream_out *stream)
2942{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002943 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002945 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946
Alexy Josephaa54c872014-12-03 02:46:47 -08002947 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002948 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002949 } else if (out->realtime) {
2950 // since the buffer won't be filled up faster than realtime,
2951 // return a smaller number
2952 if (out->config.rate)
2953 period_ms = (out->af_period_multiplier * out->config.period_size *
2954 1000) / (out->config.rate);
2955 else
2956 period_ms = 0;
2957 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002958 } else {
2959 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002960 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002961 }
2962
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002963 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2964 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2965 latency += audio_extn_a2dp_get_encoder_latency();
2966
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302967 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002968 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969}
2970
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302971static float AmpToDb(float amplification)
2972{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302973 float db = DSD_VOLUME_MIN_DB;
2974 if (amplification > 0) {
2975 db = 20 * log10(amplification);
2976 if(db < DSD_VOLUME_MIN_DB)
2977 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302978 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302979 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302980}
2981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982static int out_set_volume(struct audio_stream_out *stream, float left,
2983 float right)
2984{
Eric Laurenta9024de2013-04-04 09:19:12 -07002985 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986 int volume[2];
2987
Eric Laurenta9024de2013-04-04 09:19:12 -07002988 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2989 /* only take left channel into account: the API is for stereo anyway */
2990 out->muted = (left == 0.0f);
2991 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002992 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302993 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002994 /*
2995 * Set mute or umute on HDMI passthrough stream.
2996 * Only take left channel into account.
2997 * Mute is 0 and unmute 1
2998 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302999 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303000 } else if (out->format == AUDIO_FORMAT_DSD){
3001 char mixer_ctl_name[128] = "DSD Volume";
3002 struct audio_device *adev = out->dev;
3003 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3004
3005 if (!ctl) {
3006 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3007 __func__, mixer_ctl_name);
3008 return -EINVAL;
3009 }
3010 volume[0] = (int)(AmpToDb(left));
3011 volume[1] = (int)(AmpToDb(right));
3012 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3013 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003014 } else {
3015 char mixer_ctl_name[128];
3016 struct audio_device *adev = out->dev;
3017 struct mixer_ctl *ctl;
3018 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003019 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003021 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3022 "Compress Playback %d Volume", pcm_device_id);
3023 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3024 if (!ctl) {
3025 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3026 __func__, mixer_ctl_name);
3027 return -EINVAL;
3028 }
3029 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3030 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3031 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3032 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003034 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 return -ENOSYS;
3037}
3038
3039static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3040 size_t bytes)
3041{
3042 struct stream_out *out = (struct stream_out *)stream;
3043 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303044 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003045 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003047 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303048
Naresh Tanniru80659832014-06-04 18:17:56 +05303049 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003050
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05303051 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303052 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303053 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3054 pthread_mutex_unlock(&out->lock);
3055 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303056 } else {
3057 /* increase written size during SSR to avoid mismatch
3058 * with the written frames count in AF
3059 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003060 // bytes per frame
3061 size_t bpf = audio_bytes_per_sample(out->format) *
3062 audio_channel_count_from_out_mask(out->channel_mask);
3063 if (bpf != 0)
3064 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303065 ALOGD(" %s: sound card is not active/SSR state", __func__);
3066 ret= -EIO;
3067 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303068 }
3069 }
3070
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303071 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303072 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3073 if (audio_bytes_per_sample(out->format) != 0)
3074 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3075 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303076 goto exit;
3077 }
3078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003080 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003081 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003082 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3083 ret = voice_extn_compress_voip_start_output_stream(out);
3084 else
3085 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003086 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003089 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 goto exit;
3091 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003092
3093 if (last_known_cal_step != -1) {
3094 ALOGD("%s: retry previous failed cal level set", __func__);
3095 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3096 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098
Ashish Jain81eb2a82015-05-13 10:52:34 +05303099 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003100 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303101 adev->is_channel_status_set = true;
3102 }
3103
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003104 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003105 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003106 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003107 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003108 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3109 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303110 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3111 ALOGD("copl(%p):send next track params in gapless", out);
3112 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3113 out->send_next_track_params = false;
3114 out->is_compr_metadata_avail = false;
3115 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003116 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303117 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303118 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003119
Ashish Jain83a6cc22016-06-28 14:34:17 +05303120 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303121 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303122 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303123 pthread_mutex_unlock(&out->lock);
3124 return -EINVAL;
3125 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303126 audio_format_t dst_format = out->hal_op_format;
3127 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303128
3129 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3130 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3131
Ashish Jain83a6cc22016-06-28 14:34:17 +05303132 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303133 dst_format,
3134 buffer,
3135 src_format,
3136 frames);
3137
Ashish Jain83a6cc22016-06-28 14:34:17 +05303138 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303139 bytes_to_write);
3140
3141 /*Convert written bytes in audio flinger format*/
3142 if (ret > 0)
3143 ret = ((ret * format_to_bitwidth_table[out->format]) /
3144 format_to_bitwidth_table[dst_format]);
3145 }
3146 } else
3147 ret = compress_write(out->compr, buffer, bytes);
3148
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303149 if (ret < 0)
3150 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303151 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303152 /*msg to cb thread only if non blocking write is enabled*/
3153 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303154 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003155 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303156 } else if (-ENETRESET == ret) {
3157 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3158 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3159 pthread_mutex_unlock(&out->lock);
3160 out_standby(&out->stream.common);
3161 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003162 }
Ashish Jain5106d362016-05-11 19:23:33 +05303163 if ( ret == (ssize_t)bytes && !out->non_blocking)
3164 out->written += bytes;
3165
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303166 /* Call compr start only when non-zero bytes of data is there to be rendered */
3167 if (!out->playback_started && ret > 0) {
3168 int status = compress_start(out->compr);
3169 if (status < 0) {
3170 ret = status;
3171 ALOGE("%s: compr start failed with err %d", __func__, errno);
3172 goto exit;
3173 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003174 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003175 out->playback_started = 1;
3176 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003177
3178 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3179 popcount(out->channel_mask),
3180 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003181 }
3182 pthread_mutex_unlock(&out->lock);
3183 return ret;
3184 } else {
3185 if (out->pcm) {
3186 if (out->muted)
3187 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003188
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303189 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003190
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003191 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003192
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003193 if (out->config.rate)
3194 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3195 out->config.rate;
3196
3197 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3198
3199 request_out_focus(out, ns);
3200
3201 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003202 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003203 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303204 out->convert_buffer != NULL) {
3205
3206 memcpy_by_audio_format(out->convert_buffer,
3207 out->hal_op_format,
3208 buffer,
3209 out->hal_ip_format,
3210 out->config.period_size * out->config.channels);
3211
3212 ret = pcm_write(out->pcm, out->convert_buffer,
3213 (out->config.period_size *
3214 out->config.channels *
3215 format_to_bitwidth_table[out->hal_op_format]));
3216 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003217 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303218 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003219
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003220 release_out_focus(out);
3221
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303222 if (ret < 0)
3223 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303224 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3225 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3226 else
3227 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229 }
3230
3231exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303232 /* ToDo: There may be a corner case when SSR happens back to back during
3233 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303234 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303235 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303236 }
3237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 pthread_mutex_unlock(&out->lock);
3239
3240 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003241 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003242 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303243 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303244 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303245 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303246 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303247 out->standby = true;
3248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303250 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3251 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3252 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 }
3254 return bytes;
3255}
3256
3257static int out_get_render_position(const struct audio_stream_out *stream,
3258 uint32_t *dsp_frames)
3259{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003260 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303261 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003262
3263 if (dsp_frames == NULL)
3264 return -EINVAL;
3265
3266 *dsp_frames = 0;
3267 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003268 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303269
3270 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3271 * this operation and adev_close_output_stream(where out gets reset).
3272 */
3273 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3274 *dsp_frames = get_actual_pcm_frames_rendered(out);
3275 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3276 return 0;
3277 }
3278
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003279 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303280 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303281 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303283 if (ret < 0)
3284 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003285 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303286 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 }
3288 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303289 if (-ENETRESET == ret) {
3290 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3291 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3292 return -EINVAL;
3293 } else if(ret < 0) {
3294 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3295 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303296 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3297 /*
3298 * Handle corner case where compress session is closed during SSR
3299 * and timestamp is queried
3300 */
3301 ALOGE(" ERROR: sound card not active, return error");
3302 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303303 } else {
3304 return 0;
3305 }
Zhou Song32a556e2015-05-05 10:46:56 +08003306 } else if (audio_is_linear_pcm(out->format)) {
3307 *dsp_frames = out->written;
3308 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 } else
3310 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003313static int out_add_audio_effect(const struct audio_stream *stream __unused,
3314 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315{
3316 return 0;
3317}
3318
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003319static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3320 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
3322 return 0;
3323}
3324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003325static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3326 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327{
3328 return -EINVAL;
3329}
3330
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003331static int out_get_presentation_position(const struct audio_stream_out *stream,
3332 uint64_t *frames, struct timespec *timestamp)
3333{
3334 struct stream_out *out = (struct stream_out *)stream;
3335 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003336 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003337
Ashish Jain5106d362016-05-11 19:23:33 +05303338 /* below piece of code is not guarded against any lock because audioFliner serializes
3339 * this operation and adev_close_output_stream( where out gets reset).
3340 */
3341 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3342 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3343 *frames = get_actual_pcm_frames_rendered(out);
3344 /* this is the best we can do */
3345 clock_gettime(CLOCK_MONOTONIC, timestamp);
3346 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3347 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3348 return 0;
3349 }
3350
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003351 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003352
Ashish Jain5106d362016-05-11 19:23:33 +05303353 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3354 ret = compress_get_tstamp(out->compr, &dsp_frames,
3355 &out->sample_rate);
3356 ALOGVV("%s rendered frames %ld sample_rate %d",
3357 __func__, dsp_frames, out->sample_rate);
3358 *frames = dsp_frames;
3359 if (ret < 0)
3360 ret = -errno;
3361 if (-ENETRESET == ret) {
3362 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3363 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3364 ret = -EINVAL;
3365 } else
3366 ret = 0;
3367 /* this is the best we can do */
3368 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003369 } else {
3370 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003371 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003372 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3373 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003374 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003375 // This adjustment accounts for buffering after app processor.
3376 // It is based on estimated DSP latency per use case, rather than exact.
3377 signed_frames -=
3378 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3379
Eric Laurent949a0892013-09-20 09:20:13 -07003380 // It would be unusual for this value to be negative, but check just in case ...
3381 if (signed_frames >= 0) {
3382 *frames = signed_frames;
3383 ret = 0;
3384 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003385 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303386 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3387 *frames = out->written;
3388 clock_gettime(CLOCK_MONOTONIC, timestamp);
3389 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003390 }
3391 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003392 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003393 return ret;
3394}
3395
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003396static int out_set_callback(struct audio_stream_out *stream,
3397 stream_callback_t callback, void *cookie)
3398{
3399 struct stream_out *out = (struct stream_out *)stream;
3400
3401 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003402 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003403 out->offload_callback = callback;
3404 out->offload_cookie = cookie;
3405 pthread_mutex_unlock(&out->lock);
3406 return 0;
3407}
3408
3409static int out_pause(struct audio_stream_out* stream)
3410{
3411 struct stream_out *out = (struct stream_out *)stream;
3412 int status = -ENOSYS;
3413 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003414 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003415 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003416 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003417 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303418 struct audio_device *adev = out->dev;
3419 int snd_scard_state = get_snd_card_state(adev);
3420
3421 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3422 status = compress_pause(out->compr);
3423
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003425
Mingming Yin21854652016-04-13 11:54:02 -07003426 if (audio_extn_passthru_is_active()) {
3427 ALOGV("offload use case, pause passthru");
3428 audio_extn_passthru_on_pause(out);
3429 }
3430
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303431 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003432 audio_extn_dts_notify_playback_state(out->usecase, 0,
3433 out->sample_rate, popcount(out->channel_mask),
3434 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 }
3436 pthread_mutex_unlock(&out->lock);
3437 }
3438 return status;
3439}
3440
3441static int out_resume(struct audio_stream_out* stream)
3442{
3443 struct stream_out *out = (struct stream_out *)stream;
3444 int status = -ENOSYS;
3445 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003446 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003447 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003449 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003450 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303451 struct audio_device *adev = out->dev;
3452 int snd_scard_state = get_snd_card_state(adev);
3453
Mingming Yin21854652016-04-13 11:54:02 -07003454 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3455 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3456 pthread_mutex_lock(&out->dev->lock);
3457 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003458 pthread_mutex_unlock(&out->dev->lock);
3459 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303460 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003461 }
3462 if (!status) {
3463 out->offload_state = OFFLOAD_STATE_PLAYING;
3464 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303465 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003466 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3467 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468 }
3469 pthread_mutex_unlock(&out->lock);
3470 }
3471 return status;
3472}
3473
3474static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3475{
3476 struct stream_out *out = (struct stream_out *)stream;
3477 int status = -ENOSYS;
3478 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003479 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003480 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3482 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3483 else
3484 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3485 pthread_mutex_unlock(&out->lock);
3486 }
3487 return status;
3488}
3489
3490static int out_flush(struct audio_stream_out* stream)
3491{
3492 struct stream_out *out = (struct stream_out *)stream;
3493 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003494 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003495 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003496 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003497 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3498 stop_compressed_output_l(out);
3499 out->written = 0;
3500 } else {
3501 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3502 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003503 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003504 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 return 0;
3506 }
3507 return -ENOSYS;
3508}
3509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510/** audio_stream_in implementation **/
3511static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3512{
3513 struct stream_in *in = (struct stream_in *)stream;
3514
3515 return in->config.rate;
3516}
3517
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003518static int in_set_sample_rate(struct audio_stream *stream __unused,
3519 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520{
3521 return -ENOSYS;
3522}
3523
3524static size_t in_get_buffer_size(const struct audio_stream *stream)
3525{
3526 struct stream_in *in = (struct stream_in *)stream;
3527
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003528 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3529 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003530 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3531 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303532 else if(audio_extn_cin_attached_usecase(in->usecase))
3533 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003534
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003535 return in->config.period_size * in->af_period_multiplier *
3536 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537}
3538
3539static uint32_t in_get_channels(const struct audio_stream *stream)
3540{
3541 struct stream_in *in = (struct stream_in *)stream;
3542
3543 return in->channel_mask;
3544}
3545
3546static audio_format_t in_get_format(const struct audio_stream *stream)
3547{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003548 struct stream_in *in = (struct stream_in *)stream;
3549
3550 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551}
3552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003553static int in_set_format(struct audio_stream *stream __unused,
3554 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555{
3556 return -ENOSYS;
3557}
3558
3559static int in_standby(struct audio_stream *stream)
3560{
3561 struct stream_in *in = (struct stream_in *)stream;
3562 struct audio_device *adev = in->dev;
3563 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303564 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3565 stream, in->usecase, use_case_table[in->usecase]);
3566
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003567 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003568 if (!in->standby && in->is_st_session) {
3569 ALOGD("%s: sound trigger pcm stop lab", __func__);
3570 audio_extn_sound_trigger_stop_lab(in);
3571 in->standby = 1;
3572 }
3573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003575 if (adev->adm_deregister_stream)
3576 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3577
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003578 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003580 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3581 voice_extn_compress_voip_close_input_stream(stream);
3582 ALOGD("VOIP input entered standby");
3583 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303584 if (audio_extn_cin_attached_usecase(in->usecase))
3585 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003586 if (in->pcm) {
3587 pcm_close(in->pcm);
3588 in->pcm = NULL;
3589 }
3590 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003591 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003592 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 }
3594 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003595 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 return status;
3597}
3598
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003599static int in_dump(const struct audio_stream *stream __unused,
3600 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601{
3602 return 0;
3603}
3604
3605static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3606{
3607 struct stream_in *in = (struct stream_in *)stream;
3608 struct audio_device *adev = in->dev;
3609 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003611 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303613 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 parms = str_parms_create_str(kvpairs);
3615
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303616 if (!parms)
3617 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003618 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003619 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003620
3621 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3622 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 val = atoi(value);
3624 /* no audio source uses val == 0 */
3625 if ((in->source != val) && (val != 0)) {
3626 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003627 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3628 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3629 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003630 (in->config.rate == 8000 || in->config.rate == 16000 ||
3631 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003632 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003633 err = voice_extn_compress_voip_open_input_stream(in);
3634 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003635 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003636 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003637 }
3638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 }
3640 }
3641
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003642 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3643 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003645 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 in->device = val;
3647 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003648 if (!in->standby && !in->is_st_session) {
3649 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003650 if (adev->adm_on_routing_change)
3651 adev->adm_on_routing_change(adev->adm_data,
3652 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003653 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 }
3656 }
3657
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303658 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3659 if (err >= 0) {
3660 strlcpy(in->profile, value, sizeof(in->profile));
3661 ALOGV("updating stream profile with value '%s'", in->profile);
3662 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3663 &adev->streams_input_cfg_list,
3664 in->device, in->flags, in->format,
3665 in->sample_rate, in->bit_width,
3666 in->profile, &in->app_type_cfg);
3667 }
3668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003670 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
3672 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303673error:
Eric Laurent994a6932013-07-17 11:51:42 -07003674 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 return ret;
3676}
3677
3678static char* in_get_parameters(const struct audio_stream *stream,
3679 const char *keys)
3680{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003681 struct stream_in *in = (struct stream_in *)stream;
3682 struct str_parms *query = str_parms_create_str(keys);
3683 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003684 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003685
3686 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003687 if (reply) {
3688 str_parms_destroy(reply);
3689 }
3690 if (query) {
3691 str_parms_destroy(query);
3692 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003693 ALOGE("in_get_parameters: failed to create query or reply");
3694 return NULL;
3695 }
3696
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003697 ALOGV("%s: enter: keys - %s", __func__, keys);
3698
3699 voice_extn_in_get_parameters(in, query, reply);
3700
3701 str = str_parms_to_str(reply);
3702 str_parms_destroy(query);
3703 str_parms_destroy(reply);
3704
3705 ALOGV("%s: exit: returns - %s", __func__, str);
3706 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707}
3708
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003709static int in_set_gain(struct audio_stream_in *stream __unused,
3710 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711{
3712 return 0;
3713}
3714
3715static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3716 size_t bytes)
3717{
3718 struct stream_in *in = (struct stream_in *)stream;
3719 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303720 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303721 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303722 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003724 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303725
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003726 if (in->is_st_session) {
3727 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3728 /* Read from sound trigger HAL */
3729 audio_extn_sound_trigger_read(in, buffer, bytes);
3730 pthread_mutex_unlock(&in->lock);
3731 return bytes;
3732 }
3733
Ashish Jainbbce4322016-02-16 13:25:27 +05303734 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003735 ALOGD(" %s: sound card is not active/SSR state", __func__);
3736 ret= -EIO;;
3737 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303738 }
3739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003741 pthread_mutex_lock(&adev->lock);
3742 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3743 ret = voice_extn_compress_voip_start_input_stream(in);
3744 else
3745 ret = start_input_stream(in);
3746 pthread_mutex_unlock(&adev->lock);
3747 if (ret != 0) {
3748 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 }
3750 in->standby = 0;
3751 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003753 // what's the duration requested by the client?
3754 long ns = 0;
3755
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303756 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003757 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3758 in->config.rate;
3759
3760 request_in_focus(in, ns);
3761 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003762
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303763 if (audio_extn_cin_attached_usecase(in->usecase)) {
3764 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3765 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303766 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003767 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303768 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003769 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003770 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003771 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303772 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003773 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303774 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3775 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3776 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3777 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303778 ret = -EINVAL;
3779 goto exit;
3780 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303781 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303782 ret = -errno;
3783 }
3784 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303785 /* bytes read is always set to bytes for non compress usecases */
3786 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 }
3788
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003789 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 /*
3792 * Instead of writing zeroes here, we could trust the hardware
3793 * to always provide zeroes when muted.
3794 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303795 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3796 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 memset(buffer, 0, bytes);
3798
3799exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303800 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303801 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003802 if (-ENETRESET == ret)
3803 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 pthread_mutex_unlock(&in->lock);
3806
3807 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303808 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303809 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303810 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303811 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303812 in->standby = true;
3813 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303814 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3815 bytes_read = bytes;
3816 memset(buffer, 0, bytes);
3817 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003819 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303820 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303821 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303823 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824}
3825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003826static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827{
3828 return 0;
3829}
3830
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003831static int add_remove_audio_effect(const struct audio_stream *stream,
3832 effect_handle_t effect,
3833 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003835 struct stream_in *in = (struct stream_in *)stream;
3836 int status = 0;
3837 effect_descriptor_t desc;
3838
3839 status = (*effect)->get_descriptor(effect, &desc);
3840 if (status != 0)
3841 return status;
3842
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003843 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003844 pthread_mutex_lock(&in->dev->lock);
3845 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3846 in->enable_aec != enable &&
3847 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3848 in->enable_aec = enable;
3849 if (!in->standby)
3850 select_devices(in->dev, in->usecase);
3851 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003852 if (in->enable_ns != enable &&
3853 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3854 in->enable_ns = enable;
3855 if (!in->standby)
3856 select_devices(in->dev, in->usecase);
3857 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003858 pthread_mutex_unlock(&in->dev->lock);
3859 pthread_mutex_unlock(&in->lock);
3860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 return 0;
3862}
3863
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003864static int in_add_audio_effect(const struct audio_stream *stream,
3865 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866{
Eric Laurent994a6932013-07-17 11:51:42 -07003867 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003868 return add_remove_audio_effect(stream, effect, true);
3869}
3870
3871static int in_remove_audio_effect(const struct audio_stream *stream,
3872 effect_handle_t effect)
3873{
Eric Laurent994a6932013-07-17 11:51:42 -07003874 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003875 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876}
3877
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303878int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 audio_io_handle_t handle,
3880 audio_devices_t devices,
3881 audio_output_flags_t flags,
3882 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003883 struct audio_stream_out **stream_out,
3884 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885{
3886 struct audio_device *adev = (struct audio_device *)dev;
3887 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303888 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003889 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303892
3893 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3894 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003895 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303896 return -EINVAL;
3897 }
3898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3900
Mingming Yin3a941d42016-02-17 18:08:05 -08003901 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3902 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303903 devices, flags, &out->stream);
3904
3905
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003906 if (!out) {
3907 return -ENOMEM;
3908 }
3909
Haynes Mathew George204045b2015-02-25 20:32:03 -08003910 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003911 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003912 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 if (devices == AUDIO_DEVICE_NONE)
3915 devices = AUDIO_DEVICE_OUT_SPEAKER;
3916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 out->flags = flags;
3918 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003919 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003920 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003921 out->sample_rate = config->sample_rate;
3922 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3923 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003924 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003925 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003926 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303927 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928
Mingming Yin3a941d42016-02-17 18:08:05 -08003929 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3930 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3931 pthread_mutex_lock(&adev->lock);
3932 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3933 ret = read_hdmi_sink_caps(out);
3934 pthread_mutex_unlock(&adev->lock);
3935 if (ret != 0) {
3936 if (ret == -ENOSYS) {
3937 /* ignore and go with default */
3938 ret = 0;
3939 } else {
3940 ALOGE("error reading hdmi sink caps");
3941 goto error_open;
3942 }
3943 }
3944 }
3945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003947 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303948 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3949 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003950 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3951 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3952
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003953 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003954 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3955 /*
3956 * Do not handle stereo output in Multi-channel cases
3957 * Stereo case is handled in normal playback path
3958 */
3959 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3960 ret = AUDIO_CHANNEL_OUT_STEREO;
3961 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003962
3963 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3964 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003965 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003966 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003967 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003968
3969 if (config->sample_rate == 0)
3970 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3971 if (config->channel_mask == 0)
3972 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003973 if (config->format == 0)
3974 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003975
3976 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003978 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3980 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003982 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003984 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003985 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003986 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003987 ret = voice_extn_compress_voip_open_output_stream(out);
3988 if (ret != 0) {
3989 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3990 __func__, ret);
3991 goto error_open;
3992 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003993 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3994 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3995
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003996 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3997 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3998 ALOGE("%s: Unsupported Offload information", __func__);
3999 ret = -EINVAL;
4000 goto error_open;
4001 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004002
Mingming Yin3a941d42016-02-17 18:08:05 -08004003 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004004 if(config->offload_info.format == 0)
4005 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004006 if (config->offload_info.sample_rate == 0)
4007 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004008 }
4009
Mingming Yin90310102013-11-13 16:57:00 -08004010 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304011 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004012 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004013 ret = -EINVAL;
4014 goto error_open;
4015 }
4016
4017 out->compr_config.codec = (struct snd_codec *)
4018 calloc(1, sizeof(struct snd_codec));
4019
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004020 if (!out->compr_config.codec) {
4021 ret = -ENOMEM;
4022 goto error_open;
4023 }
4024
vivek mehta0ea887a2015-08-26 14:01:20 -07004025 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304026 out->stream.pause = out_pause;
4027 out->stream.flush = out_flush;
4028 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07004029 out->usecase = get_offload_usecase(adev, true);
4030 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004031 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07004032 out->stream.set_callback = out_set_callback;
4033 out->stream.pause = out_pause;
4034 out->stream.resume = out_resume;
4035 out->stream.drain = out_drain;
4036 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07004037 out->usecase = get_offload_usecase(adev, false);
4038 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004039 }
vivek mehta446c3962015-09-14 10:57:35 -07004040
4041 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004042 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4043 config->format == 0 && config->sample_rate == 0 &&
4044 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004045 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004046 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4047 } else {
4048 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4049 ret = -EEXIST;
4050 goto error_open;
4051 }
vivek mehta446c3962015-09-14 10:57:35 -07004052 }
4053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004054 if (config->offload_info.channel_mask)
4055 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004056 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004057 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004058 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004059 } else {
4060 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
4061 ret = -EINVAL;
4062 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004063 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004064
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004065 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066 out->sample_rate = config->offload_info.sample_rate;
4067
Mingming Yin3ee55c62014-08-04 14:23:35 -07004068 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004069
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304070 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4071 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4072 audio_extn_dolby_send_ddp_endp_params(adev);
4073 audio_extn_dolby_set_dmid(adev);
4074 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004076 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004077 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004078 out->compr_config.codec->bit_rate =
4079 config->offload_info.bit_rate;
4080 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304081 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004082 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304083 /* Update bit width only for non passthrough usecases.
4084 * For passthrough usecases, the output will always be opened @16 bit
4085 */
4086 if (!audio_extn_passthru_is_passthrough_stream(out))
4087 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004088 /*TODO: Do we need to change it for passthrough */
4089 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004090
Manish Dewangana6fc5442015-08-24 20:30:31 +05304091 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4092 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304093 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304094 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304095 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4096 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304097
4098 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4099 AUDIO_FORMAT_PCM) {
4100
4101 /*Based on platform support, configure appropriate alsa format for corresponding
4102 *hal input format.
4103 */
4104 out->compr_config.codec->format = hal_format_to_alsa(
4105 config->offload_info.format);
4106
Ashish Jain83a6cc22016-06-28 14:34:17 +05304107 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304108 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304109 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304110
4111 /*for direct PCM playback populate bit_width based on selected alsa format as
4112 *hal input format and alsa format might differ based on platform support.
4113 */
4114 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304115 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304116
4117 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4118
4119 /* Check if alsa session is configured with the same format as HAL input format,
4120 * if not then derive correct fragment size needed to accomodate the
4121 * conversion of HAL input format to alsa format.
4122 */
4123 audio_extn_utils_update_direct_pcm_fragment_size(out);
4124
4125 /*if hal input and output fragment size is different this indicates HAL input format is
4126 *not same as the alsa format
4127 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304128 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304129 /*Allocate a buffer to convert input data to the alsa configured format.
4130 *size of convert buffer is equal to the size required to hold one fragment size
4131 *worth of pcm data, this is because flinger does not write more than fragment_size
4132 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304133 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4134 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304135 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4136 ret = -ENOMEM;
4137 goto error_open;
4138 }
4139 }
4140 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4141 out->compr_config.fragment_size =
4142 audio_extn_passthru_get_buffer_size(&config->offload_info);
4143 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4144 } else {
4145 out->compr_config.fragment_size =
4146 platform_get_compress_offload_buffer_size(&config->offload_info);
4147 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4148 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004149
Amit Shekhar6f461b12014-08-01 14:52:58 -07004150 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304151 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004152
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304153 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4154 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4155 }
4156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004157 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4158 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004159
Alexy Josephaa54c872014-12-03 02:46:47 -08004160
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004161 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304162 out->send_next_track_params = false;
4163 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004164 out->offload_state = OFFLOAD_STATE_IDLE;
4165 out->playback_started = 0;
4166
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004167 audio_extn_dts_create_state_notifier_node(out->usecase);
4168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004169 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4170 __func__, config->offload_info.version,
4171 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304172
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304173 /* Check if DSD audio format is supported in codec
4174 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304175 */
4176
4177 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304178 (!platform_check_codec_dsd_support(adev->platform) ||
4179 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304180 ret = -EINVAL;
4181 goto error_open;
4182 }
4183
Ashish Jain5106d362016-05-11 19:23:33 +05304184 /* Disable gapless if any of the following is true
4185 * passthrough playback
4186 * AV playback
4187 * Direct PCM playback
4188 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304189 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304190 (config->format == AUDIO_FORMAT_DSD) ||
4191 config->offload_info.has_video ||
4192 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304193 check_and_set_gapless_mode(adev, false);
4194 } else
4195 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004196
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304197 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004198 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4199 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304200 if (config->format == AUDIO_FORMAT_DSD) {
4201 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4202 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4203 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004204
4205 create_offload_callback_thread(out);
4206
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004207 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304208 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004209 if (ret != 0) {
4210 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4211 __func__, ret);
4212 goto error_open;
4213 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004214 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4215 if (config->sample_rate == 0)
4216 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4217 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4218 config->sample_rate != 8000) {
4219 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4220 ret = -EINVAL;
4221 goto error_open;
4222 }
4223 out->sample_rate = config->sample_rate;
4224 out->config.rate = config->sample_rate;
4225 if (config->format == AUDIO_FORMAT_DEFAULT)
4226 config->format = AUDIO_FORMAT_PCM_16_BIT;
4227 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4228 config->format = AUDIO_FORMAT_PCM_16_BIT;
4229 ret = -EINVAL;
4230 goto error_open;
4231 }
4232 out->format = config->format;
4233 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4234 out->config = pcm_config_afe_proxy_playback;
4235 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004236 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304237 unsigned int channels = 0;
4238 /*Update config params to default if not set by the caller*/
4239 if (config->sample_rate == 0)
4240 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4241 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4242 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4243 if (config->format == AUDIO_FORMAT_DEFAULT)
4244 config->format = AUDIO_FORMAT_PCM_16_BIT;
4245
4246 channels = audio_channel_count_from_out_mask(out->channel_mask);
4247
Ashish Jain83a6cc22016-06-28 14:34:17 +05304248 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4249 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004250 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4251 out->flags);
4252 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304253 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4254 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4255 out->config = pcm_config_low_latency;
4256 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4257 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4258 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304259 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4260 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4261 if (out->config.period_size <= 0) {
4262 ALOGE("Invalid configuration period size is not valid");
4263 ret = -EINVAL;
4264 goto error_open;
4265 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304266 } else {
4267 /* primary path is the default path selected if no other outputs are available/suitable */
4268 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4269 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4270 }
4271 out->hal_ip_format = format = out->format;
4272 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4273 out->hal_op_format = pcm_format_to_hal(out->config.format);
4274 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4275 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004276 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304277 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304278 if (out->hal_ip_format != out->hal_op_format) {
4279 uint32_t buffer_size = out->config.period_size *
4280 format_to_bitwidth_table[out->hal_op_format] *
4281 out->config.channels;
4282 out->convert_buffer = calloc(1, buffer_size);
4283 if (out->convert_buffer == NULL){
4284 ALOGE("Allocation failed for convert buffer for size %d",
4285 out->compr_config.fragment_size);
4286 ret = -ENOMEM;
4287 goto error_open;
4288 }
4289 ALOGD("Convert buffer allocated of size %d", buffer_size);
4290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 }
4292
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004293 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4294 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304295
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004296 /* TODO remove this hardcoding and check why width is zero*/
4297 if (out->bit_width == 0)
4298 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304299 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004300 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304301 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304302 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304303 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004304 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4305 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4306 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004307 if(adev->primary_output == NULL)
4308 adev->primary_output = out;
4309 else {
4310 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004311 ret = -EEXIST;
4312 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004313 }
4314 }
4315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 /* Check if this usecase is already existing */
4317 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004318 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4319 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004322 ret = -EEXIST;
4323 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 pthread_mutex_unlock(&adev->lock);
4327
4328 out->stream.common.get_sample_rate = out_get_sample_rate;
4329 out->stream.common.set_sample_rate = out_set_sample_rate;
4330 out->stream.common.get_buffer_size = out_get_buffer_size;
4331 out->stream.common.get_channels = out_get_channels;
4332 out->stream.common.get_format = out_get_format;
4333 out->stream.common.set_format = out_set_format;
4334 out->stream.common.standby = out_standby;
4335 out->stream.common.dump = out_dump;
4336 out->stream.common.set_parameters = out_set_parameters;
4337 out->stream.common.get_parameters = out_get_parameters;
4338 out->stream.common.add_audio_effect = out_add_audio_effect;
4339 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4340 out->stream.get_latency = out_get_latency;
4341 out->stream.set_volume = out_set_volume;
4342 out->stream.write = out_write;
4343 out->stream.get_render_position = out_get_render_position;
4344 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004345 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004347 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004349 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004350 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351
4352 config->format = out->stream.common.get_format(&out->stream.common);
4353 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4354 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4355
4356 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304357 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004358 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004359
4360 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4361 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4362 popcount(out->channel_mask), out->playback_started);
4363
Eric Laurent994a6932013-07-17 11:51:42 -07004364 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004366
4367error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304368 if (out->convert_buffer)
4369 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004370 free(out);
4371 *stream_out = NULL;
4372 ALOGD("%s: exit: ret %d", __func__, ret);
4373 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374}
4375
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304376void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 struct audio_stream_out *stream)
4378{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004379 struct stream_out *out = (struct stream_out *)stream;
4380 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004381 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004382
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304383 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4384
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004385 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304386 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004387 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304388 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004389 if(ret != 0)
4390 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4391 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004392 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004393 out_standby(&stream->common);
4394
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004395 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004396 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004397 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004398 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004399 if (out->compr_config.codec != NULL)
4400 free(out->compr_config.codec);
4401 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004402
Ashish Jain83a6cc22016-06-28 14:34:17 +05304403 if (out->convert_buffer != NULL) {
4404 free(out->convert_buffer);
4405 out->convert_buffer = NULL;
4406 }
4407
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004408 if (adev->voice_tx_output == out)
4409 adev->voice_tx_output = NULL;
4410
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304411 if (adev->primary_output == out)
4412 adev->primary_output = NULL;
4413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004414 pthread_cond_destroy(&out->cond);
4415 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004417 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418}
4419
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004420static void close_compress_sessions(struct audio_device *adev)
4421{
Mingming Yin7b762e72015-03-04 13:47:32 -08004422 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304423 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004424 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004425 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304426
4427 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004428 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304429 if (is_offload_usecase(usecase->id)) {
4430 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004431 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4432 out = usecase->stream.out;
4433 pthread_mutex_unlock(&adev->lock);
4434 out_standby(&out->stream.common);
4435 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004436 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004437 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304438 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004439 }
4440 pthread_mutex_unlock(&adev->lock);
4441}
4442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4444{
4445 struct audio_device *adev = (struct audio_device *)dev;
4446 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004447 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004448 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004449 int ret;
4450 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004452 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304455 if (!parms)
4456 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004457 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4458 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304459 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304460 if (strstr(snd_card_status, "OFFLINE")) {
4461 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304462 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004463 //close compress sessions on OFFLINE status
4464 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304465 } else if (strstr(snd_card_status, "ONLINE")) {
4466 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304467 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004468 //send dts hpx license if enabled
4469 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304470 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304471 }
4472
4473 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004474 status = voice_set_parameters(adev, parms);
4475 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004476 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004478 status = platform_set_parameters(adev->platform, parms);
4479 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004480 goto done;
4481
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004482 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4483 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004484 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4486 adev->bluetooth_nrec = true;
4487 else
4488 adev->bluetooth_nrec = false;
4489 }
4490
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004491 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4492 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4494 adev->screen_off = false;
4495 else
4496 adev->screen_off = true;
4497 }
4498
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004499 ret = str_parms_get_int(parms, "rotation", &val);
4500 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004501 bool reverse_speakers = false;
4502 switch(val) {
4503 // FIXME: note that the code below assumes that the speakers are in the correct placement
4504 // relative to the user when the device is rotated 90deg from its default rotation. This
4505 // assumption is device-specific, not platform-specific like this code.
4506 case 270:
4507 reverse_speakers = true;
4508 break;
4509 case 0:
4510 case 90:
4511 case 180:
4512 break;
4513 default:
4514 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004515 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004516 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004517 if (status == 0) {
4518 if (adev->speaker_lr_swap != reverse_speakers) {
4519 adev->speaker_lr_swap = reverse_speakers;
4520 // only update the selected device if there is active pcm playback
4521 struct audio_usecase *usecase;
4522 struct listnode *node;
4523 list_for_each(node, &adev->usecase_list) {
4524 usecase = node_to_item(node, struct audio_usecase, list);
4525 if (usecase->type == PCM_PLAYBACK) {
4526 select_devices(adev, usecase->id);
4527 break;
4528 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004529 }
4530 }
4531 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004532 }
4533
Mingming Yin514a8bc2014-07-29 15:22:21 -07004534 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4535 if (ret >= 0) {
4536 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4537 adev->bt_wb_speech_enabled = true;
4538 else
4539 adev->bt_wb_speech_enabled = false;
4540 }
4541
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004542 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4543 if (ret >= 0) {
4544 val = atoi(value);
4545 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004546 ALOGV("cache new ext disp type and edid");
4547 ret = platform_get_ext_disp_type(adev->platform);
4548 if (ret < 0) {
4549 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004550 status = ret;
4551 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004552 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004553 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004554 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004555 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004556 /*
4557 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4558 * Per AudioPolicyManager, USB device is higher priority than WFD.
4559 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4560 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4561 * starting voice call on USB
4562 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004563 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4564 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004565 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4566 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004567 }
vivek mehta344576a2016-04-12 18:56:03 -07004568 ALOGV("detected USB connect .. disable proxy");
4569 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004570 }
4571 }
4572
4573 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4574 if (ret >= 0) {
4575 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004576 /*
4577 * The HDMI / Displayport disconnect handling has been moved to
4578 * audio extension to ensure that its parameters are not
4579 * invalidated prior to updating sysfs of the disconnect event
4580 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4581 */
4582 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004583 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004584 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4585 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304586 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4587 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004588 }
vivek mehta344576a2016-04-12 18:56:03 -07004589 ALOGV("detected USB disconnect .. enable proxy");
4590 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004591 }
4592 }
4593
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304594 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4595 if (ret >= 0) {
4596 struct audio_usecase *usecase;
4597 struct listnode *node;
4598 list_for_each(node, &adev->usecase_list) {
4599 usecase = node_to_item(node, struct audio_usecase, list);
4600 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004601 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304602 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304603 lock_output_stream(usecase->stream.out);
4604 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304605 //force device switch to re configure encoder
4606 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304607 audio_extn_a2dp_set_handoff_mode(false);
4608 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304609 break;
4610 }
4611 }
4612 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004613
4614 //handle vr audio setparam
4615 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4616 value, sizeof(value));
4617 if (ret >= 0) {
4618 ALOGI("Setting vr mode to be %s", value);
4619 if (!strncmp(value, "true", 4)) {
4620 adev->vr_audio_mode_enabled = true;
4621 ALOGI("Setting vr mode to true");
4622 } else if (!strncmp(value, "false", 5)) {
4623 adev->vr_audio_mode_enabled = false;
4624 ALOGI("Setting vr mode to false");
4625 } else {
4626 ALOGI("wrong vr mode set");
4627 }
4628 }
4629
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304630 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004631done:
4632 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004633 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304634error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004635 ALOGV("%s: exit with code(%d)", __func__, status);
4636 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637}
4638
4639static char* adev_get_parameters(const struct audio_hw_device *dev,
4640 const char *keys)
4641{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004642 struct audio_device *adev = (struct audio_device *)dev;
4643 struct str_parms *reply = str_parms_create();
4644 struct str_parms *query = str_parms_create_str(keys);
4645 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304646 char value[256] = {0};
4647 int ret = 0;
4648
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004649 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004650 if (reply) {
4651 str_parms_destroy(reply);
4652 }
4653 if (query) {
4654 str_parms_destroy(query);
4655 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004656 ALOGE("adev_get_parameters: failed to create query or reply");
4657 return NULL;
4658 }
4659
Naresh Tannirud7205b62014-06-20 02:54:48 +05304660 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4661 sizeof(value));
4662 if (ret >=0) {
4663 int val = 1;
4664 pthread_mutex_lock(&adev->snd_card_status.lock);
4665 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4666 val = 0;
4667 pthread_mutex_unlock(&adev->snd_card_status.lock);
4668 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4669 goto exit;
4670 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004671 //handle vr audio getparam
4672
4673 ret = str_parms_get_str(query,
4674 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4675 value, sizeof(value));
4676
4677 if (ret >= 0) {
4678 bool vr_audio_enabled = false;
4679 pthread_mutex_lock(&adev->lock);
4680 vr_audio_enabled = adev->vr_audio_mode_enabled;
4681 pthread_mutex_unlock(&adev->lock);
4682
4683 ALOGI("getting vr mode to %d", vr_audio_enabled);
4684
4685 if (vr_audio_enabled) {
4686 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4687 "true");
4688 goto exit;
4689 } else {
4690 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4691 "false");
4692 goto exit;
4693 }
4694 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004695
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004696 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004697 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004698 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004699 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304700 pthread_mutex_unlock(&adev->lock);
4701
Naresh Tannirud7205b62014-06-20 02:54:48 +05304702exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004703 str = str_parms_to_str(reply);
4704 str_parms_destroy(query);
4705 str_parms_destroy(reply);
4706
4707 ALOGV("%s: exit: returns - %s", __func__, str);
4708 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709}
4710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004711static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712{
4713 return 0;
4714}
4715
4716static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4717{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004718 int ret;
4719 struct audio_device *adev = (struct audio_device *)dev;
4720 pthread_mutex_lock(&adev->lock);
4721 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004722 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004723 pthread_mutex_unlock(&adev->lock);
4724 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725}
4726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004727static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4728 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004729{
4730 return -ENOSYS;
4731}
4732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004733static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4734 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004735{
4736 return -ENOSYS;
4737}
4738
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004739static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4740 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741{
4742 return -ENOSYS;
4743}
4744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004745static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4746 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747{
4748 return -ENOSYS;
4749}
4750
4751static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4752{
4753 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004755 pthread_mutex_lock(&adev->lock);
4756 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004757 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004759 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004760 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004761 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004762 adev->current_call_output = NULL;
4763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 }
4765 pthread_mutex_unlock(&adev->lock);
4766 return 0;
4767}
4768
4769static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4770{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004771 int ret;
4772
4773 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004774 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004775 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4776 pthread_mutex_unlock(&adev->lock);
4777
4778 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004779}
4780
4781static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4782{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004783 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784 return 0;
4785}
4786
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004787static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788 const struct audio_config *config)
4789{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004790 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004792 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4793 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794}
4795
4796static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004797 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 audio_devices_t devices,
4799 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004800 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304801 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004802 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004803 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804{
4805 struct audio_device *adev = (struct audio_device *)dev;
4806 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004807 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004808 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004809 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304810 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304813 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4814 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817
4818 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004819
4820 if (!in) {
4821 ALOGE("failed to allocate input stream");
4822 return -ENOMEM;
4823 }
4824
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304825 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304826 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4827 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004828 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004829 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831 in->stream.common.get_sample_rate = in_get_sample_rate;
4832 in->stream.common.set_sample_rate = in_set_sample_rate;
4833 in->stream.common.get_buffer_size = in_get_buffer_size;
4834 in->stream.common.get_channels = in_get_channels;
4835 in->stream.common.get_format = in_get_format;
4836 in->stream.common.set_format = in_set_format;
4837 in->stream.common.standby = in_standby;
4838 in->stream.common.dump = in_dump;
4839 in->stream.common.set_parameters = in_set_parameters;
4840 in->stream.common.get_parameters = in_get_parameters;
4841 in->stream.common.add_audio_effect = in_add_audio_effect;
4842 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4843 in->stream.set_gain = in_set_gain;
4844 in->stream.read = in_read;
4845 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4846
4847 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004848 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850 in->standby = 1;
4851 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004852 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004853 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304855 in->usecase = USECASE_AUDIO_RECORD;
4856 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4857 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4858 is_low_latency = true;
4859#if LOW_LATENCY_CAPTURE_USE_CASE
4860 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4861#endif
4862 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4863 }
4864
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004865 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004866 if (in->realtime) {
4867 in->config = pcm_config_audio_capture_rt;
4868 in->sample_rate = in->config.rate;
4869 in->af_period_multiplier = af_period_multiplier;
4870 } else {
4871 in->config = pcm_config_audio_capture;
4872 in->config.rate = config->sample_rate;
4873 in->sample_rate = config->sample_rate;
4874 in->af_period_multiplier = 1;
4875 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304876 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304878 /* restrict 24 bit capture for unprocessed source only
4879 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4880 */
4881 if (config->format == AUDIO_FORMAT_DEFAULT) {
4882 config->format = AUDIO_FORMAT_PCM_16_BIT;
4883 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4884 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4885 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4886 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4887 bool ret_error = false;
4888 in->bit_width = 24;
4889 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4890 from HAL is 24_packed and 8_24
4891 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4892 24_packed return error indicating supported format is 24_packed
4893 *> In case of any other source requesting 24 bit or float return error
4894 indicating format supported is 16 bit only.
4895
4896 on error flinger will retry with supported format passed
4897 */
4898 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4899 (source != AUDIO_SOURCE_CAMCORDER)) {
4900 config->format = AUDIO_FORMAT_PCM_16_BIT;
4901 if (config->sample_rate > 48000)
4902 config->sample_rate = 48000;
4903 ret_error = true;
4904 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4905 in->config.format = PCM_FORMAT_S24_3LE;
4906 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4907 in->config.format = PCM_FORMAT_S24_LE;
4908 } else {
4909 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4910 ret_error = true;
4911 }
4912
4913 if (ret_error) {
4914 ret = -EINVAL;
4915 goto err_open;
4916 }
4917 }
4918
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304919 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304920 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4921 (adev->mode != AUDIO_MODE_IN_CALL)) {
4922 ret = -EINVAL;
4923 goto err_open;
4924 }
4925
4926 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4927 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004928 if (config->sample_rate == 0)
4929 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4930 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4931 config->sample_rate != 8000) {
4932 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4933 ret = -EINVAL;
4934 goto err_open;
4935 }
4936 if (config->format == AUDIO_FORMAT_DEFAULT)
4937 config->format = AUDIO_FORMAT_PCM_16_BIT;
4938 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4939 config->format = AUDIO_FORMAT_PCM_16_BIT;
4940 ret = -EINVAL;
4941 goto err_open;
4942 }
4943
4944 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4945 in->config = pcm_config_afe_proxy_record;
4946 in->config.channels = channel_count;
4947 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304948 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304949 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4950 in, config, &channel_mask_updated)) {
4951 if (channel_mask_updated == true) {
4952 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4953 __func__, config->channel_mask);
4954 ret = -EINVAL;
4955 goto err_open;
4956 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304957 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004958 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004959 audio_extn_compr_cap_format_supported(config->format) &&
4960 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004961 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304962 } else if (audio_extn_cin_applicable_stream(in)) {
4963 ret = audio_extn_cin_configure_input_stream(in);
4964 if (ret)
4965 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004966 } else {
4967 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004968 if (!in->realtime) {
4969 in->format = config->format;
4970 frame_size = audio_stream_in_frame_size(&in->stream);
4971 buffer_size = get_input_buffer_size(config->sample_rate,
4972 config->format,
4973 channel_count,
4974 is_low_latency);
4975 in->config.period_size = buffer_size / frame_size;
4976 }
4977
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004978 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004979 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004980 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004981 (in->config.rate == 8000 || in->config.rate == 16000 ||
4982 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004983 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4984 voice_extn_compress_voip_open_input_stream(in);
4985 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304988 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4989 &adev->streams_input_cfg_list,
4990 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304991 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304992
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004993 /* This stream could be for sound trigger lab,
4994 get sound trigger pcm if present */
4995 audio_extn_sound_trigger_check_and_get_session(in);
4996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004998 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004999 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000
5001err_open:
5002 free(in);
5003 *stream_in = NULL;
5004 return ret;
5005}
5006
5007static void adev_close_input_stream(struct audio_hw_device *dev,
5008 struct audio_stream_in *stream)
5009{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005010 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005011 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005012 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305013
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305014 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005015
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305016 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005017 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305018
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005019 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305020 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005021 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305022 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005023 if (ret != 0)
5024 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5025 __func__, ret);
5026 } else
5027 in_standby(&stream->common);
5028
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005029 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005030 audio_extn_ssr_deinit();
5031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305033 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005034 audio_extn_compr_cap_format_supported(in->config.format))
5035 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305036
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305037 if (audio_extn_cin_attached_usecase(in->usecase))
5038 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005039
Mingming Yinfd7607b2016-01-22 12:48:44 -08005040 if (in->is_st_session) {
5041 ALOGV("%s: sound trigger pcm stop lab", __func__);
5042 audio_extn_sound_trigger_stop_lab(in);
5043 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005044 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045 return;
5046}
5047
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005048static int adev_dump(const audio_hw_device_t *device __unused,
5049 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050{
5051 return 0;
5052}
5053
5054static int adev_close(hw_device_t *device)
5055{
5056 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005057
5058 if (!adev)
5059 return 0;
5060
5061 pthread_mutex_lock(&adev_init_lock);
5062
5063 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005064 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005065 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305066 audio_extn_utils_release_streams_cfg_lists(
5067 &adev->streams_output_cfg_list,
5068 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305069 if (audio_extn_qaf_is_enabled())
5070 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005071 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005072 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005073 free(adev->snd_dev_ref_cnt);
5074 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005075 if (adev->adm_deinit)
5076 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305077 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005078 free(device);
5079 adev = NULL;
5080 }
5081 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005083 return 0;
5084}
5085
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005086/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5087 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5088 * just that it _might_ work.
5089 */
5090static int period_size_is_plausible_for_low_latency(int period_size)
5091{
5092 switch (period_size) {
5093 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005094 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005095 case 240:
5096 case 320:
5097 case 480:
5098 return 1;
5099 default:
5100 return 0;
5101 }
5102}
5103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005104static int adev_open(const hw_module_t *module, const char *name,
5105 hw_device_t **device)
5106{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305107 int ret;
5108
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005109 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5111
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005112 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005113 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005114 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005115 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005116 ALOGD("%s: returning existing instance of adev", __func__);
5117 ALOGD("%s: exit", __func__);
5118 pthread_mutex_unlock(&adev_init_lock);
5119 return 0;
5120 }
5121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005122 adev = calloc(1, sizeof(struct audio_device));
5123
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005124 if (!adev) {
5125 pthread_mutex_unlock(&adev_init_lock);
5126 return -ENOMEM;
5127 }
5128
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005129 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5132 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5133 adev->device.common.module = (struct hw_module_t *)module;
5134 adev->device.common.close = adev_close;
5135
5136 adev->device.init_check = adev_init_check;
5137 adev->device.set_voice_volume = adev_set_voice_volume;
5138 adev->device.set_master_volume = adev_set_master_volume;
5139 adev->device.get_master_volume = adev_get_master_volume;
5140 adev->device.set_master_mute = adev_set_master_mute;
5141 adev->device.get_master_mute = adev_get_master_mute;
5142 adev->device.set_mode = adev_set_mode;
5143 adev->device.set_mic_mute = adev_set_mic_mute;
5144 adev->device.get_mic_mute = adev_get_mic_mute;
5145 adev->device.set_parameters = adev_set_parameters;
5146 adev->device.get_parameters = adev_get_parameters;
5147 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5148 adev->device.open_output_stream = adev_open_output_stream;
5149 adev->device.close_output_stream = adev_close_output_stream;
5150 adev->device.open_input_stream = adev_open_input_stream;
5151 adev->device.close_input_stream = adev_close_input_stream;
5152 adev->device.dump = adev_dump;
5153
5154 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005156 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005157 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005160 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005161 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005162 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005163 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005164 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005165 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005166 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005167 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305168 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305169 adev->perf_lock_opts[0] = 0x101;
5170 adev->perf_lock_opts[1] = 0x20E;
5171 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305172
5173 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5174 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005175 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005176 adev->platform = platform_init(adev);
5177 if (!adev->platform) {
5178 free(adev->snd_dev_ref_cnt);
5179 free(adev);
5180 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5181 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005182 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305183 pthread_mutex_destroy(&adev->lock);
5184 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005185 return -EINVAL;
5186 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005187
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305188 if (audio_extn_qaf_is_enabled()) {
5189 ret = audio_extn_qaf_init(adev);
5190 if (ret < 0) {
5191 free(adev);
5192 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5193 *device = NULL;
5194 pthread_mutex_unlock(&adev_init_lock);
5195 pthread_mutex_destroy(&adev->lock);
5196 return ret;
5197 }
5198
5199 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5200 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5201 }
5202
Naresh Tanniru4c630392014-05-12 01:05:52 +05305203 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5204
Eric Laurentc4aef752013-09-12 17:45:53 -07005205 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5206 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5207 if (adev->visualizer_lib == NULL) {
5208 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5209 } else {
5210 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5211 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005212 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005213 "visualizer_hal_start_output");
5214 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005215 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005216 "visualizer_hal_stop_output");
5217 }
5218 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305219 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005220 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005221 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005222 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005223
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005224 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5225 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5226 if (adev->offload_effects_lib == NULL) {
5227 ALOGE("%s: DLOPEN failed for %s", __func__,
5228 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5229 } else {
5230 ALOGV("%s: DLOPEN successful for %s", __func__,
5231 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5232 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305233 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005234 "offload_effects_bundle_hal_start_output");
5235 adev->offload_effects_stop_output =
5236 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5237 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005238 adev->offload_effects_set_hpx_state =
5239 (int (*)(bool))dlsym(adev->offload_effects_lib,
5240 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305241 adev->offload_effects_get_parameters =
5242 (void (*)(struct str_parms *, struct str_parms *))
5243 dlsym(adev->offload_effects_lib,
5244 "offload_effects_bundle_get_parameters");
5245 adev->offload_effects_set_parameters =
5246 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5247 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005248 }
5249 }
5250
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005251 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5252 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5253 if (adev->adm_lib == NULL) {
5254 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5255 } else {
5256 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5257 adev->adm_init = (adm_init_t)
5258 dlsym(adev->adm_lib, "adm_init");
5259 adev->adm_deinit = (adm_deinit_t)
5260 dlsym(adev->adm_lib, "adm_deinit");
5261 adev->adm_register_input_stream = (adm_register_input_stream_t)
5262 dlsym(adev->adm_lib, "adm_register_input_stream");
5263 adev->adm_register_output_stream = (adm_register_output_stream_t)
5264 dlsym(adev->adm_lib, "adm_register_output_stream");
5265 adev->adm_deregister_stream = (adm_deregister_stream_t)
5266 dlsym(adev->adm_lib, "adm_deregister_stream");
5267 adev->adm_request_focus = (adm_request_focus_t)
5268 dlsym(adev->adm_lib, "adm_request_focus");
5269 adev->adm_abandon_focus = (adm_abandon_focus_t)
5270 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005271 adev->adm_set_config = (adm_set_config_t)
5272 dlsym(adev->adm_lib, "adm_set_config");
5273 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5274 dlsym(adev->adm_lib, "adm_request_focus_v2");
5275 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5276 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5277 adev->adm_on_routing_change = (adm_on_routing_change_t)
5278 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005279 }
5280 }
5281
Mingming Yin514a8bc2014-07-29 15:22:21 -07005282 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005283 //initialize this to false for now,
5284 //this will be set to true through set param
5285 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005286
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005287 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288 *device = &adev->device.common;
5289
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305290 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5291 &adev->streams_output_cfg_list,
5292 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005293
Kiran Kandi910e1862013-10-29 13:29:42 -07005294 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005295
5296 char value[PROPERTY_VALUE_MAX];
5297 int trial;
5298 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5299 trial = atoi(value);
5300 if (period_size_is_plausible_for_low_latency(trial)) {
5301 pcm_config_low_latency.period_size = trial;
5302 pcm_config_low_latency.start_threshold = trial / 4;
5303 pcm_config_low_latency.avail_min = trial / 4;
5304 configured_low_latency_capture_period_size = trial;
5305 }
5306 }
5307 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5308 trial = atoi(value);
5309 if (period_size_is_plausible_for_low_latency(trial)) {
5310 configured_low_latency_capture_period_size = trial;
5311 }
5312 }
5313
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005314 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5315 af_period_multiplier = atoi(value);
5316 if (af_period_multiplier < 0)
5317 af_period_multiplier = 2;
5318 else if (af_period_multiplier > 4)
5319 af_period_multiplier = 4;
5320
5321 ALOGV("new period_multiplier = %d", af_period_multiplier);
5322 }
5323
vivek mehta446c3962015-09-14 10:57:35 -07005324 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005325 pthread_mutex_unlock(&adev_init_lock);
5326
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005327 if (adev->adm_init)
5328 adev->adm_data = adev->adm_init();
5329
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305330 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305331 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005332 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005333 return 0;
5334}
5335
5336static struct hw_module_methods_t hal_module_methods = {
5337 .open = adev_open,
5338};
5339
5340struct audio_module HAL_MODULE_INFO_SYM = {
5341 .common = {
5342 .tag = HARDWARE_MODULE_TAG,
5343 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5344 .hal_api_version = HARDWARE_HAL_API_VERSION,
5345 .id = AUDIO_HARDWARE_MODULE_ID,
5346 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005347 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005348 .methods = &hal_module_methods,
5349 },
5350};