blob: 09c5a967793fb43ffe8025d9c186d82cbcc34db1 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700475static bool is_supported_format(audio_format_t format)
476{
Eric Laurent86e17132013-09-12 17:49:30 -0700477 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530478 format == AUDIO_FORMAT_AAC_LC ||
479 format == AUDIO_FORMAT_AAC_HE_V1 ||
480 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530481 format == AUDIO_FORMAT_AAC_ADTS_LC ||
482 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
483 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530484 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
485 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530486 format == AUDIO_FORMAT_PCM_FLOAT ||
487 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700488 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530489 format == AUDIO_FORMAT_AC3 ||
490 format == AUDIO_FORMAT_E_AC3 ||
491 format == AUDIO_FORMAT_DTS ||
492 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800493 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530494 format == AUDIO_FORMAT_ALAC ||
495 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530496 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530497 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800498 format == AUDIO_FORMAT_WMA ||
499 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800500 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700501
502 return false;
503}
504
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700505static inline bool is_mmap_usecase(audio_usecase_t uc_id)
506{
507 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
508 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
509}
510
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530511int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530512{
513 int snd_scard_state;
514
515 if (!adev)
516 return SND_CARD_STATE_OFFLINE;
517
518 pthread_mutex_lock(&adev->snd_card_status.lock);
519 snd_scard_state = adev->snd_card_status.state;
520 pthread_mutex_unlock(&adev->snd_card_status.lock);
521
522 return snd_scard_state;
523}
524
525static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
526{
527 if (!adev)
528 return -ENOSYS;
529
530 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700531 if (adev->snd_card_status.state != snd_scard_state) {
532 adev->snd_card_status.state = snd_scard_state;
533 platform_snd_card_update(adev->platform, snd_scard_state);
534 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530535 pthread_mutex_unlock(&adev->snd_card_status.lock);
536
537 return 0;
538}
539
Avinash Vaish71a8b972014-07-24 15:36:33 +0530540static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
541 struct audio_usecase *uc_info)
542{
543 struct listnode *node;
544 struct audio_usecase *usecase;
545
546 if (uc_info == NULL)
547 return -EINVAL;
548
549 /* Re-route all voice usecases on the shared backend other than the
550 specified usecase to new snd devices */
551 list_for_each(node, &adev->usecase_list) {
552 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800553 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530554 enable_audio_route(adev, usecase);
555 }
556 return 0;
557}
558
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530559static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530560{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530561 ALOGV("%s", __func__);
562 audio_route_apply_and_update_path(adev->audio_route,
563 "asrc-mode");
564 adev->asrc_mode_enabled = true;
565}
566
567static void disable_asrc_mode(struct audio_device *adev)
568{
569 ALOGV("%s", __func__);
570 audio_route_reset_and_update_path(adev->audio_route,
571 "asrc-mode");
572 adev->asrc_mode_enabled = false;
573}
574
575/*
576 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
577 * 44.1 or Native DSD backends are enabled for any of current use case.
578 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
579 * - Disable current mix path use case(Headphone backend) and re-enable it with
580 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
581 * e.g. Naitve DSD or Headphone 44.1 -> + 48
582 */
583static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
584{
585 ALOGV("%s snd device %d", __func__, snd_device);
586 int new_backend_idx = platform_get_backend_index(snd_device);
587
588 if (((new_backend_idx == HEADPHONE_BACKEND) ||
589 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
590 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
591 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530592 struct listnode *node = NULL;
593 struct audio_usecase *uc = NULL;
594 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530595 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530596
597 list_for_each(node, &adev->usecase_list) {
598 uc = node_to_item(node, struct audio_usecase, list);
599 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530600 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530601 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
602
603 if((new_backend_idx == HEADPHONE_BACKEND) &&
604 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
605 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530606 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
607 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530608 enable_asrc_mode(adev);
609 break;
610 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
611 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
612 (usecase_backend_idx == HEADPHONE_BACKEND)) {
613 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
614 __func__);
615 disable_audio_route(adev, uc);
616 disable_snd_device(adev, uc->out_snd_device);
617 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
618 if (new_backend_idx == DSD_NATIVE_BACKEND)
619 audio_route_apply_and_update_path(adev->audio_route,
620 "hph-true-highquality-mode");
621 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
622 (curr_out->bit_width >= 24))
623 audio_route_apply_and_update_path(adev->audio_route,
624 "hph-highquality-mode");
625 enable_asrc_mode(adev);
626 enable_snd_device(adev, uc->out_snd_device);
627 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530628 break;
629 }
630 }
631 }
632 }
633}
634
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700635int pcm_ioctl(struct pcm *pcm, int request, ...)
636{
637 va_list ap;
638 void * arg;
639 int pcm_fd = *(int*)pcm;
640
641 va_start(ap, request);
642 arg = va_arg(ap, void *);
643 va_end(ap);
644
645 return ioctl(pcm_fd, request, arg);
646}
647
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700648int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700649 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800650{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700652 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800653
654 if (usecase == NULL)
655 return -EINVAL;
656
657 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
658
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800659 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800661 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800663
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800664#ifdef DS1_DOLBY_DAP_ENABLED
665 audio_extn_dolby_set_dmid(adev);
666 audio_extn_dolby_set_endpoint(adev);
667#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700668 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700669 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530670 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700671 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530672 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800673 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700674 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700675 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700676 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677 ALOGV("%s: exit", __func__);
678 return 0;
679}
680
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700681int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700682 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800683{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700685 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800686
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530687 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800688 return -EINVAL;
689
690 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691 if (usecase->type == PCM_CAPTURE)
692 snd_device = usecase->in_snd_device;
693 else
694 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800695 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700696 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700697 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700698 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700699 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530700 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701 ALOGV("%s: exit", __func__);
702 return 0;
703}
704
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700705int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700706 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530708 int i, num_devices = 0;
709 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700710 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
711
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800712 if (snd_device < SND_DEVICE_MIN ||
713 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800714 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800715 return -EINVAL;
716 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717
718 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700719
720 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
721 ALOGE("%s: Invalid sound device returned", __func__);
722 return -EINVAL;
723 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700725 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700726 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700727 return 0;
728 }
729
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530730
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700731 if (audio_extn_spkr_prot_is_enabled())
732 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700733
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800734 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
735 audio_extn_spkr_prot_is_enabled()) {
736 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700737 adev->snd_dev_ref_cnt[snd_device]--;
738 return -EINVAL;
739 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200740 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800741 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800742 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200743 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800744 return -EINVAL;
745 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700746 } else if (platform_split_snd_device(adev->platform,
747 snd_device,
748 &num_devices,
749 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530750 for (i = 0; i < num_devices; i++) {
751 enable_snd_device(adev, new_snd_devices[i]);
752 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800753 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700754 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530755
756 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
757 (audio_extn_a2dp_start_playback() < 0)) {
758 ALOGE(" fail to configure A2dp control path ");
759 return -EINVAL;
760 }
761
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700762 /* due to the possibility of calibration overwrite between listen
763 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700764 audio_extn_sound_trigger_update_device_status(snd_device,
765 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530766 audio_extn_listen_update_device_status(snd_device,
767 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700768 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700769 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700770 audio_extn_sound_trigger_update_device_status(snd_device,
771 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530772 audio_extn_listen_update_device_status(snd_device,
773 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700774 return -EINVAL;
775 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300776 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700777 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530778
779 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
780 !adev->native_playback_enabled &&
781 audio_is_true_native_stream_active(adev)) {
782 ALOGD("%s: %d: napb: enabling native mode in hardware",
783 __func__, __LINE__);
784 audio_route_apply_and_update_path(adev->audio_route,
785 "true-native-mode");
786 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 return 0;
790}
791
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700792int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700793 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800794{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530795 int i, num_devices = 0;
796 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700797 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
798
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800799 if (snd_device < SND_DEVICE_MIN ||
800 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800801 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800802 return -EINVAL;
803 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
805 ALOGE("%s: device ref cnt is already 0", __func__);
806 return -EINVAL;
807 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700808
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700809 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700810
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700811 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
812 ALOGE("%s: Invalid sound device returned", __func__);
813 return -EINVAL;
814 }
815
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700816 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700817 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530818
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800819 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
820 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700821 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700822 } else if (platform_split_snd_device(adev->platform,
823 snd_device,
824 &num_devices,
825 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530826 for (i = 0; i < num_devices; i++) {
827 disable_snd_device(adev, new_snd_devices[i]);
828 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300829 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700830 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300831 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700832
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530833 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
834 audio_extn_a2dp_stop_playback();
835
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700836 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530837 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530838 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
839 adev->native_playback_enabled) {
840 ALOGD("%s: %d: napb: disabling native mode in hardware",
841 __func__, __LINE__);
842 audio_route_reset_and_update_path(adev->audio_route,
843 "true-native-mode");
844 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530845 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
846 adev->asrc_mode_enabled) {
847 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530848 disable_asrc_mode(adev);
849 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530850 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530851
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200852 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700853 audio_extn_sound_trigger_update_device_status(snd_device,
854 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530855 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800856 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800859 return 0;
860}
861
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700862/*
863 legend:
864 uc - existing usecase
865 new_uc - new usecase
866 d1, d11, d2 - SND_DEVICE enums
867 a1, a2 - corresponding ANDROID device enums
868 B1, B2 - backend strings
869
870case 1
871 uc->dev d1 (a1) B1
872 new_uc->dev d1 (a1), d2 (a2) B1, B2
873
874 resolution: disable and enable uc->dev on d1
875
876case 2
877 uc->dev d1 (a1) B1
878 new_uc->dev d11 (a1) B1
879
880 resolution: need to switch uc since d1 and d11 are related
881 (e.g. speaker and voice-speaker)
882 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
883
884case 3
885 uc->dev d1 (a1) B1
886 new_uc->dev d2 (a2) B2
887
888 resolution: no need to switch uc
889
890case 4
891 uc->dev d1 (a1) B1
892 new_uc->dev d2 (a2) B1
893
894 resolution: disable enable uc-dev on d2 since backends match
895 we cannot enable two streams on two different devices if they
896 share the same backend. e.g. if offload is on speaker device using
897 QUAD_MI2S backend and a low-latency stream is started on voice-handset
898 using the same backend, offload must also be switched to voice-handset.
899
900case 5
901 uc->dev d1 (a1) B1
902 new_uc->dev d1 (a1), d2 (a2) B1
903
904 resolution: disable enable uc-dev on d2 since backends match
905 we cannot enable two streams on two different devices if they
906 share the same backend.
907
908case 6
909 uc->dev d1 (a1) B1
910 new_uc->dev d2 (a1) B2
911
912 resolution: no need to switch
913
914case 7
915 uc->dev d1 (a1), d2 (a2) B1, B2
916 new_uc->dev d1 (a1) B1
917
918 resolution: no need to switch
919
920*/
921static snd_device_t derive_playback_snd_device(void * platform,
922 struct audio_usecase *uc,
923 struct audio_usecase *new_uc,
924 snd_device_t new_snd_device)
925{
926 audio_devices_t a1 = uc->stream.out->devices;
927 audio_devices_t a2 = new_uc->stream.out->devices;
928
929 snd_device_t d1 = uc->out_snd_device;
930 snd_device_t d2 = new_snd_device;
931
932 // Treat as a special case when a1 and a2 are not disjoint
933 if ((a1 != a2) && (a1 & a2)) {
934 snd_device_t d3[2];
935 int num_devices = 0;
936 int ret = platform_split_snd_device(platform,
937 popcount(a1) > 1 ? d1 : d2,
938 &num_devices,
939 d3);
940 if (ret < 0) {
941 if (ret != -ENOSYS) {
942 ALOGW("%s failed to split snd_device %d",
943 __func__,
944 popcount(a1) > 1 ? d1 : d2);
945 }
946 goto end;
947 }
948
949 // NB: case 7 is hypothetical and isn't a practical usecase yet.
950 // But if it does happen, we need to give priority to d2 if
951 // the combo devices active on the existing usecase share a backend.
952 // This is because we cannot have a usecase active on a combo device
953 // and a new usecase requests one device in this combo pair.
954 if (platform_check_backends_match(d3[0], d3[1])) {
955 return d2; // case 5
956 } else {
957 return d1; // case 1
958 }
959 } else {
960 if (platform_check_backends_match(d1, d2)) {
961 return d2; // case 2, 4
962 } else {
963 return d1; // case 6, 3
964 }
965 }
966
967end:
968 return d2; // return whatever was calculated before.
969}
970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530972 struct audio_usecase *uc_info,
973 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974{
975 struct listnode *node;
976 struct audio_usecase *usecase;
977 bool switch_device[AUDIO_USECASE_MAX];
978 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530979 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 /*
981 * This function is to make sure that all the usecases that are active on
982 * the hardware codec backend are always routed to any one device that is
983 * handled by the hardware codec.
984 * For example, if low-latency and deep-buffer usecases are currently active
985 * on speaker and out_set_parameters(headset) is received on low-latency
986 * output, then we have to make sure deep-buffer is also switched to headset,
987 * because of the limitation that both the devices cannot be enabled
988 * at the same time as they share the same backend.
989 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700990 /*
991 * This call is to check if we need to force routing for a particular stream
992 * If there is a backend configuration change for the device when a
993 * new stream starts, then ADM needs to be closed and re-opened with the new
994 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800995 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700996 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800997 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
998 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530999 /* For a2dp device reconfigure all active sessions
1000 * with new AFE encoder format based on a2dp state
1001 */
1002 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1003 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1004 audio_extn_a2dp_is_force_device_switch()) {
1005 force_routing = true;
1006 force_restart_session = true;
1007 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301008 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1009
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001011 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001012 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001018
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301019 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1020 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301021 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301022 platform_get_snd_device_name(usecase->out_snd_device),
1023 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001024 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301025 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001026 (derive_playback_snd_device(adev->platform,
1027 usecase, uc_info,
1028 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301029 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1030 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301031 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301032 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301033 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
1034
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301035 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1036 __func__, use_case_table[usecase->id],
1037 platform_get_snd_device_name(usecase->out_snd_device));
1038 disable_audio_route(adev, usecase);
1039 switch_device[usecase->id] = true;
1040 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 }
1042 }
1043
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301044 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1045 num_uc_to_switch);
1046
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001048 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301050 /* Make sure the previous devices to be disabled first and then enable the
1051 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052 list_for_each(node, &adev->usecase_list) {
1053 usecase = node_to_item(node, struct audio_usecase, list);
1054 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001055 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 }
1057 }
1058
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001059 list_for_each(node, &adev->usecase_list) {
1060 usecase = node_to_item(node, struct audio_usecase, list);
1061 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001062 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001063 }
1064 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001065
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001066 /* Re-route all the usecases on the shared backend other than the
1067 specified usecase to new snd devices */
1068 list_for_each(node, &adev->usecase_list) {
1069 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301070 /* Update the out_snd_device only before enabling the audio route */
1071 if (switch_device[usecase->id]) {
1072 usecase->out_snd_device = snd_device;
1073 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301074 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301075 use_case_table[usecase->id],
1076 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301077 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301078 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 }
1080 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081 }
1082}
1083
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301084static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001085 struct audio_usecase *uc_info,
1086 snd_device_t snd_device)
1087{
1088 struct listnode *node;
1089 struct audio_usecase *usecase;
1090 bool switch_device[AUDIO_USECASE_MAX];
1091 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301092 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001093
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301094 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1095 snd_device);
1096 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301097
1098 /*
1099 * Make sure out devices is checked against out codec backend device and
1100 * also in devices against in codec backend. Checking out device against in
1101 * codec backend or vice versa causes issues.
1102 */
1103 if (uc_info->type == PCM_CAPTURE)
1104 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001105 /*
1106 * This function is to make sure that all the active capture usecases
1107 * are always routed to the same input sound device.
1108 * For example, if audio-record and voice-call usecases are currently
1109 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1110 * is received for voice call then we have to make sure that audio-record
1111 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1112 * because of the limitation that two devices cannot be enabled
1113 * at the same time if they share the same backend.
1114 */
1115 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1116 switch_device[i] = false;
1117
1118 list_for_each(node, &adev->usecase_list) {
1119 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301120 /*
1121 * TODO: Enhance below condition to handle BT sco/USB multi recording
1122 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001123 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001124 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301125 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301126 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301127 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001128 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001129 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001130 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1131 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001132 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001133 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001134 switch_device[usecase->id] = true;
1135 num_uc_to_switch++;
1136 }
1137 }
1138
1139 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001140 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001141
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301142 /* Make sure the previous devices to be disabled first and then enable the
1143 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001144 list_for_each(node, &adev->usecase_list) {
1145 usecase = node_to_item(node, struct audio_usecase, list);
1146 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001147 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001148 }
1149 }
1150
1151 list_for_each(node, &adev->usecase_list) {
1152 usecase = node_to_item(node, struct audio_usecase, list);
1153 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001154 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001155 }
1156 }
1157
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001158 /* Re-route all the usecases on the shared backend other than the
1159 specified usecase to new snd devices */
1160 list_for_each(node, &adev->usecase_list) {
1161 usecase = node_to_item(node, struct audio_usecase, list);
1162 /* Update the in_snd_device only before enabling the audio route */
1163 if (switch_device[usecase->id] ) {
1164 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001165 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301166 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001167 }
1168 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001169 }
1170}
1171
Mingming Yin3a941d42016-02-17 18:08:05 -08001172static void reset_hdmi_sink_caps(struct stream_out *out) {
1173 int i = 0;
1174
1175 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1176 out->supported_channel_masks[i] = 0;
1177 }
1178 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1179 out->supported_formats[i] = 0;
1180 }
1181 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1182 out->supported_sample_rates[i] = 0;
1183 }
1184}
1185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001186/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001187static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188{
Mingming Yin3a941d42016-02-17 18:08:05 -08001189 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001190 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191
Mingming Yin3a941d42016-02-17 18:08:05 -08001192 reset_hdmi_sink_caps(out);
1193
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001194 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001195 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001196 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001197 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001198 }
1199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001202 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001203 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001204 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1205 case 6:
1206 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1207 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1208 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1209 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1210 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1211 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 break;
1213 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001214 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001215 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216 break;
1217 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001218
1219 // check channel format caps
1220 i = 0;
1221 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1222 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1223 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1224 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1225 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1226 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1227 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1228 }
1229
1230 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1231 ALOGV(":%s HDMI supports DTS format", __func__);
1232 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1233 }
1234
1235 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1236 ALOGV(":%s HDMI supports DTS HD format", __func__);
1237 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1238 }
1239
1240
1241 // check sample rate caps
1242 i = 0;
1243 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1244 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1245 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1246 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1247 }
1248 }
1249
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001250 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251}
1252
Alexy Josephb1379942016-01-29 15:49:38 -08001253audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001254 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001255{
1256 struct audio_usecase *usecase;
1257 struct listnode *node;
1258
1259 list_for_each(node, &adev->usecase_list) {
1260 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001261 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001262 ALOGV("%s: usecase id %d", __func__, usecase->id);
1263 return usecase->id;
1264 }
1265 }
1266 return USECASE_INVALID;
1267}
1268
Alexy Josephb1379942016-01-29 15:49:38 -08001269struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001270 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001271{
1272 struct audio_usecase *usecase;
1273 struct listnode *node;
1274
1275 list_for_each(node, &adev->usecase_list) {
1276 usecase = node_to_item(node, struct audio_usecase, list);
1277 if (usecase->id == uc_id)
1278 return usecase;
1279 }
1280 return NULL;
1281}
1282
Dhananjay Kumard4833242016-10-06 22:09:12 +05301283struct stream_in *get_next_active_input(const struct audio_device *adev)
1284{
1285 struct audio_usecase *usecase;
1286 struct listnode *node;
1287
1288 list_for_each_reverse(node, &adev->usecase_list) {
1289 usecase = node_to_item(node, struct audio_usecase, list);
1290 if (usecase->type == PCM_CAPTURE)
1291 return usecase->stream.in;
1292 }
1293 return NULL;
1294}
1295
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301296/*
1297 * is a true native playback active
1298 */
1299bool audio_is_true_native_stream_active(struct audio_device *adev)
1300{
1301 bool active = false;
1302 int i = 0;
1303 struct listnode *node;
1304
1305 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1306 ALOGV("%s:napb: not in true mode or non hdphones device",
1307 __func__);
1308 active = false;
1309 goto exit;
1310 }
1311
1312 list_for_each(node, &adev->usecase_list) {
1313 struct audio_usecase *uc;
1314 uc = node_to_item(node, struct audio_usecase, list);
1315 struct stream_out *curr_out =
1316 (struct stream_out*) uc->stream.out;
1317
1318 if (curr_out && PCM_PLAYBACK == uc->type) {
1319 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1320 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1321 uc->id, curr_out->sample_rate,
1322 curr_out->bit_width,
1323 platform_get_snd_device_name(uc->out_snd_device));
1324
1325 if (is_offload_usecase(uc->id) &&
1326 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1327 active = true;
1328 ALOGD("%s:napb:native stream detected", __func__);
1329 }
1330 }
1331 }
1332exit:
1333 return active;
1334}
1335
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301336/*
1337 * if native DSD playback active
1338 */
1339bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1340{
1341 bool active = false;
1342 struct listnode *node = NULL;
1343 struct audio_usecase *uc = NULL;
1344 struct stream_out *curr_out = NULL;
1345
1346 list_for_each(node, &adev->usecase_list) {
1347 uc = node_to_item(node, struct audio_usecase, list);
1348 curr_out = (struct stream_out*) uc->stream.out;
1349
1350 if (curr_out && PCM_PLAYBACK == uc->type &&
1351 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1352 active = true;
1353 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301354 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301355 }
1356 }
1357 return active;
1358}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301359
1360static bool force_device_switch(struct audio_usecase *usecase)
1361{
1362 bool ret = false;
1363 bool is_it_true_mode = false;
1364
1365 if (is_offload_usecase(usecase->id) &&
1366 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001367 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1368 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1369 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301370 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1371 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1372 (!is_it_true_mode && adev->native_playback_enabled)){
1373 ret = true;
1374 ALOGD("napb: time to toggle native mode");
1375 }
1376 }
1377
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301378 // Force all a2dp output devices to reconfigure for proper AFE encode format
1379 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001380 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301381 audio_extn_a2dp_is_force_device_switch()) {
1382 ALOGD("Force a2dp device switch to update new encoder config");
1383 ret = true;
1384 }
1385
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301386 return ret;
1387}
1388
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001389int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001390{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001391 snd_device_t out_snd_device = SND_DEVICE_NONE;
1392 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393 struct audio_usecase *usecase = NULL;
1394 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001395 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001396 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001397 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001398 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301400 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1401
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001402 usecase = get_usecase_from_list(adev, uc_id);
1403 if (usecase == NULL) {
1404 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1405 return -EINVAL;
1406 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001408 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001409 (usecase->type == VOIP_CALL) ||
1410 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301411 if(usecase->stream.out == NULL) {
1412 ALOGE("%s: stream.out is NULL", __func__);
1413 return -EINVAL;
1414 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001415 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001416 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001417 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001418 usecase->devices = usecase->stream.out->devices;
1419 } else {
1420 /*
1421 * If the voice call is active, use the sound devices of voice call usecase
1422 * so that it would not result any device switch. All the usecases will
1423 * be switched to new device when select_devices() is called for voice call
1424 * usecase. This is to avoid switching devices for voice call when
1425 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001426 * choose voice call device only if the use case device is
1427 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001428 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001429 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001430 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001431 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001432 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1433 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301434 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1435 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001436 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001437 in_snd_device = vc_usecase->in_snd_device;
1438 out_snd_device = vc_usecase->out_snd_device;
1439 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001440 } else if (voice_extn_compress_voip_is_active(adev)) {
1441 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001442 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001443 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1444 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001445 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001446 in_snd_device = voip_usecase->in_snd_device;
1447 out_snd_device = voip_usecase->out_snd_device;
1448 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001449 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001450 hfp_ucid = audio_extn_hfp_get_usecase();
1451 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001452 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001453 in_snd_device = hfp_usecase->in_snd_device;
1454 out_snd_device = hfp_usecase->out_snd_device;
1455 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 }
1457 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301458 if (usecase->stream.out == NULL) {
1459 ALOGE("%s: stream.out is NULL", __func__);
1460 return -EINVAL;
1461 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 usecase->devices = usecase->stream.out->devices;
1463 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001464 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001465 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001466 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001467 if (usecase->stream.out == adev->primary_output &&
1468 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001469 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001470 select_devices(adev, adev->active_input->usecase);
1471 }
1472 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301474 if (usecase->stream.in == NULL) {
1475 ALOGE("%s: stream.in is NULL", __func__);
1476 return -EINVAL;
1477 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 usecase->devices = usecase->stream.in->device;
1479 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001480 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001481 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001482 if (adev->active_input &&
1483 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301484 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1485 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1486 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001487 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001488 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001489 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1490 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001491 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001492 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001493 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 }
1495 }
1496
1497 if (out_snd_device == usecase->out_snd_device &&
1498 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301499
1500 if (!force_device_switch(usecase))
1501 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502 }
1503
sangwoobc677242013-08-08 16:53:43 +09001504 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001505 out_snd_device, platform_get_snd_device_name(out_snd_device),
1506 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 /*
1509 * Limitation: While in call, to do a device switch we need to disable
1510 * and enable both RX and TX devices though one of them is same as current
1511 * device.
1512 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001513 if ((usecase->type == VOICE_CALL) &&
1514 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1515 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001516 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001517 }
1518
1519 if (((usecase->type == VOICE_CALL) ||
1520 (usecase->type == VOIP_CALL)) &&
1521 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1522 /* Disable sidetone only if voice/voip call already exists */
1523 if (voice_is_call_state_active(adev) ||
1524 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001525 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001526
1527 /* Disable aanc only if voice call exists */
1528 if (voice_is_call_state_active(adev))
1529 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001530 }
1531
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 /* Disable current sound devices */
1533 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001534 disable_audio_route(adev, usecase);
1535 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 }
1537
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001539 disable_audio_route(adev, usecase);
1540 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 }
1542
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001543 /* Applicable only on the targets that has external modem.
1544 * New device information should be sent to modem before enabling
1545 * the devices to reduce in-call device switch time.
1546 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001547 if ((usecase->type == VOICE_CALL) &&
1548 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1549 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001550 status = platform_switch_voice_call_enable_device_config(adev->platform,
1551 out_snd_device,
1552 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001553 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001554
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 /* Enable new sound devices */
1556 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001557 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301558 if (platform_check_codec_asrc_support(adev->platform))
1559 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001560 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561 }
1562
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001563 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301564 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001565 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567
Avinash Vaish71a8b972014-07-24 15:36:33 +05301568 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001569 status = platform_switch_voice_call_device_post(adev->platform,
1570 out_snd_device,
1571 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301572 enable_audio_route_for_voice_usecases(adev, usecase);
1573 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001574
sangwoo170731f2013-06-08 15:36:36 +09001575 usecase->in_snd_device = in_snd_device;
1576 usecase->out_snd_device = out_snd_device;
1577
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301578 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1579 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301580 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001581 /* Notify device change info to effect clients registered */
1582 audio_extn_gef_notify_device_config(
1583 usecase->stream.out->devices,
1584 usecase->stream.out->channel_mask,
1585 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301586 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001587 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001588
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001589 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001590 /* Enable aanc only if voice call exists */
1591 if (voice_is_call_state_active(adev))
1592 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1593
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001594 /* Enable sidetone only if other voice/voip call already exists */
1595 if (voice_is_call_state_active(adev) ||
1596 voice_extn_compress_voip_is_started(adev))
1597 voice_set_sidetone(adev, out_snd_device, true);
1598 }
1599
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001600 /* Applicable only on the targets that has external modem.
1601 * Enable device command should be sent to modem only after
1602 * enabling voice call mixer controls
1603 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001604 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001605 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1606 out_snd_device,
1607 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301608 ALOGD("%s: done",__func__);
1609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 return status;
1611}
1612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613static int stop_input_stream(struct stream_in *in)
1614{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301615 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 struct audio_usecase *uc_info;
1617 struct audio_device *adev = in->dev;
1618
Dhananjay Kumard4833242016-10-06 22:09:12 +05301619 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620
Eric Laurent994a6932013-07-17 11:51:42 -07001621 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 uc_info = get_usecase_from_list(adev, in->usecase);
1624 if (uc_info == NULL) {
1625 ALOGE("%s: Could not find the usecase (%d) in the list",
1626 __func__, in->usecase);
1627 return -EINVAL;
1628 }
1629
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001630 /* Close in-call recording streams */
1631 voice_check_and_stop_incall_rec_usecase(adev, in);
1632
Eric Laurent150dbfe2013-02-27 14:31:02 -08001633 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001634 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001635
1636 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001637 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001639 list_remove(&uc_info->list);
1640 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Eric Laurent994a6932013-07-17 11:51:42 -07001642 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 return ret;
1644}
1645
1646int start_input_stream(struct stream_in *in)
1647{
1648 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001649 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 struct audio_usecase *uc_info;
1651 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301652 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653
Mingming Yin2664a5b2015-09-03 10:53:11 -07001654 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1655 if (get_usecase_from_list(adev, usecase) == NULL)
1656 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301657 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1658 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001659
Naresh Tanniru80659832014-06-04 18:17:56 +05301660
1661 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301662 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301663 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301664 goto error_config;
1665 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301666
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001667 /* Check if source matches incall recording usecase criteria */
1668 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1669 if (ret)
1670 goto error_config;
1671 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001672 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1673
1674 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1675 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1676 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001677 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001678 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001679
Eric Laurentb23d5282013-05-14 15:27:20 -07001680 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681 if (in->pcm_device_id < 0) {
1682 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1683 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001684 ret = -EINVAL;
1685 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001687
1688 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001690
1691 if (!uc_info) {
1692 ret = -ENOMEM;
1693 goto error_config;
1694 }
1695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 uc_info->id = in->usecase;
1697 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001698 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001699 uc_info->devices = in->device;
1700 uc_info->in_snd_device = SND_DEVICE_NONE;
1701 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001703 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301704 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1705 adev->perf_lock_opts,
1706 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301709 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1710 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001711
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301712 if (audio_extn_cin_attached_usecase(in->usecase)) {
1713 ret = audio_extn_cin_start_input_stream(in);
1714 if (ret)
1715 goto error_open;
1716 else
1717 goto done_open;
1718 }
1719
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001720 unsigned int flags = PCM_IN;
1721 unsigned int pcm_open_retry_count = 0;
1722
1723 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1724 flags |= PCM_MMAP | PCM_NOIRQ;
1725 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001726 } else if (in->realtime) {
1727 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001728 }
1729
1730 while (1) {
1731 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1732 flags, &in->config);
1733 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1734 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1735 if (in->pcm != NULL) {
1736 pcm_close(in->pcm);
1737 in->pcm = NULL;
1738 }
1739 if (pcm_open_retry_count-- == 0) {
1740 ret = -EIO;
1741 goto error_open;
1742 }
1743 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1744 continue;
1745 }
1746 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001748
1749 ALOGV("%s: pcm_prepare", __func__);
1750 ret = pcm_prepare(in->pcm);
1751 if (ret < 0) {
1752 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1753 pcm_close(in->pcm);
1754 in->pcm = NULL;
1755 goto error_open;
1756 }
1757
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001758 register_in_stream(in);
1759 if (in->realtime) {
1760 ret = pcm_start(in->pcm);
1761 if (ret < 0)
1762 goto error_open;
1763 }
1764
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301765done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301766 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001767 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001768
Eric Laurentc8400632013-02-14 19:04:54 -08001769 return ret;
1770
1771error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301772 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001774error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301775 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301776 /*
1777 * sleep 50ms to allow sufficient time for kernel
1778 * drivers to recover incases like SSR.
1779 */
1780 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001781 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001782
1783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784}
1785
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001786void lock_input_stream(struct stream_in *in)
1787{
1788 pthread_mutex_lock(&in->pre_lock);
1789 pthread_mutex_lock(&in->lock);
1790 pthread_mutex_unlock(&in->pre_lock);
1791}
1792
1793void lock_output_stream(struct stream_out *out)
1794{
1795 pthread_mutex_lock(&out->pre_lock);
1796 pthread_mutex_lock(&out->lock);
1797 pthread_mutex_unlock(&out->pre_lock);
1798}
1799
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800/* must be called with out->lock locked */
1801static int send_offload_cmd_l(struct stream_out* out, int command)
1802{
1803 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1804
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001805 if (!cmd) {
1806 ALOGE("failed to allocate mem for command 0x%x", command);
1807 return -ENOMEM;
1808 }
1809
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001810 ALOGVV("%s %d", __func__, command);
1811
1812 cmd->cmd = command;
1813 list_add_tail(&out->offload_cmd_list, &cmd->node);
1814 pthread_cond_signal(&out->offload_cond);
1815 return 0;
1816}
1817
1818/* must be called iwth out->lock locked */
1819static void stop_compressed_output_l(struct stream_out *out)
1820{
1821 out->offload_state = OFFLOAD_STATE_IDLE;
1822 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 if (out->compr != NULL) {
1825 compress_stop(out->compr);
1826 while (out->offload_thread_blocked) {
1827 pthread_cond_wait(&out->cond, &out->lock);
1828 }
1829 }
1830}
1831
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001832bool is_offload_usecase(audio_usecase_t uc_id)
1833{
1834 unsigned int i;
1835 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1836 if (uc_id == offload_usecases[i])
1837 return true;
1838 }
1839 return false;
1840}
1841
vivek mehta446c3962015-09-14 10:57:35 -07001842static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001843{
vivek mehta446c3962015-09-14 10:57:35 -07001844 audio_usecase_t ret_uc = USECASE_INVALID;
1845 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001846 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001847 if (!adev->multi_offload_enable) {
1848 if (is_direct_pcm)
1849 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1850 else
1851 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001852
vivek mehta446c3962015-09-14 10:57:35 -07001853 pthread_mutex_lock(&adev->lock);
1854 if (get_usecase_from_list(adev, ret_uc) != NULL)
1855 ret_uc = USECASE_INVALID;
1856 pthread_mutex_unlock(&adev->lock);
1857
1858 return ret_uc;
1859 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001860
1861 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001862 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1863 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1864 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1865 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001866 break;
1867 }
1868 }
vivek mehta446c3962015-09-14 10:57:35 -07001869
1870 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1871 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001872}
1873
1874static void free_offload_usecase(struct audio_device *adev,
1875 audio_usecase_t uc_id)
1876{
vivek mehta446c3962015-09-14 10:57:35 -07001877 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001878 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001879
1880 if (!adev->multi_offload_enable)
1881 return;
1882
1883 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1884 if (offload_usecases[offload_uc_index] == uc_id) {
1885 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001886 break;
1887 }
1888 }
1889 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1890}
1891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892static void *offload_thread_loop(void *context)
1893{
1894 struct stream_out *out = (struct stream_out *) context;
1895 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001896 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1899 set_sched_policy(0, SP_FOREGROUND);
1900 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1901
1902 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001903 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001904 for (;;) {
1905 struct offload_cmd *cmd = NULL;
1906 stream_callback_event_t event;
1907 bool send_callback = false;
1908
1909 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1910 __func__, list_empty(&out->offload_cmd_list),
1911 out->offload_state);
1912 if (list_empty(&out->offload_cmd_list)) {
1913 ALOGV("%s SLEEPING", __func__);
1914 pthread_cond_wait(&out->offload_cond, &out->lock);
1915 ALOGV("%s RUNNING", __func__);
1916 continue;
1917 }
1918
1919 item = list_head(&out->offload_cmd_list);
1920 cmd = node_to_item(item, struct offload_cmd, node);
1921 list_remove(item);
1922
1923 ALOGVV("%s STATE %d CMD %d out->compr %p",
1924 __func__, out->offload_state, cmd->cmd, out->compr);
1925
1926 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1927 free(cmd);
1928 break;
1929 }
1930
1931 if (out->compr == NULL) {
1932 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001933 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 pthread_cond_signal(&out->cond);
1935 continue;
1936 }
1937 out->offload_thread_blocked = true;
1938 pthread_mutex_unlock(&out->lock);
1939 send_callback = false;
1940 switch(cmd->cmd) {
1941 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001942 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001944 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945 send_callback = true;
1946 event = STREAM_CBK_EVENT_WRITE_READY;
1947 break;
1948 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001949 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301950 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001951 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301952 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001953 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301954 if (ret < 0)
1955 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301956 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301957 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001958 compress_drain(out->compr);
1959 else
1960 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301961 if (ret != -ENETRESET) {
1962 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301963 pthread_mutex_lock(&out->lock);
1964 out->send_new_metadata = 1;
1965 out->send_next_track_params = true;
1966 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301967 event = STREAM_CBK_EVENT_DRAIN_READY;
1968 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1969 } else
1970 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001971 break;
1972 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001973 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001975 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001976 send_callback = true;
1977 event = STREAM_CBK_EVENT_DRAIN_READY;
1978 break;
1979 default:
1980 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1981 break;
1982 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001983 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 out->offload_thread_blocked = false;
1985 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001986 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001987 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001989 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 free(cmd);
1991 }
1992
1993 pthread_cond_signal(&out->cond);
1994 while (!list_empty(&out->offload_cmd_list)) {
1995 item = list_head(&out->offload_cmd_list);
1996 list_remove(item);
1997 free(node_to_item(item, struct offload_cmd, node));
1998 }
1999 pthread_mutex_unlock(&out->lock);
2000
2001 return NULL;
2002}
2003
2004static int create_offload_callback_thread(struct stream_out *out)
2005{
2006 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2007 list_init(&out->offload_cmd_list);
2008 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2009 offload_thread_loop, out);
2010 return 0;
2011}
2012
2013static int destroy_offload_callback_thread(struct stream_out *out)
2014{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002015 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 stop_compressed_output_l(out);
2017 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2018
2019 pthread_mutex_unlock(&out->lock);
2020 pthread_join(out->offload_thread, (void **) NULL);
2021 pthread_cond_destroy(&out->offload_cond);
2022
2023 return 0;
2024}
2025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026static int stop_output_stream(struct stream_out *out)
2027{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302028 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 struct audio_usecase *uc_info;
2030 struct audio_device *adev = out->dev;
2031
Eric Laurent994a6932013-07-17 11:51:42 -07002032 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002033 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 uc_info = get_usecase_from_list(adev, out->usecase);
2035 if (uc_info == NULL) {
2036 ALOGE("%s: Could not find the usecase (%d) in the list",
2037 __func__, out->usecase);
2038 return -EINVAL;
2039 }
2040
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002041 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302042 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002043 if (adev->visualizer_stop_output != NULL)
2044 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002045
2046 audio_extn_dts_remove_state_notifier_node(out->usecase);
2047
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002048 if (adev->offload_effects_stop_output != NULL)
2049 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2050 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002051
Eric Laurent150dbfe2013-02-27 14:31:02 -08002052 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002053 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054
2055 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002056 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002058 list_remove(&uc_info->list);
2059 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002061 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302062 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002063 ALOGV("Disable passthrough , reset mixer to pcm");
2064 /* NO_PASSTHROUGH */
2065 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002066 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002067 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2068 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002069
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302070 /* Must be called after removing the usecase from list */
2071 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302072 audio_extn_keep_alive_start();
2073
Eric Laurent994a6932013-07-17 11:51:42 -07002074 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 return ret;
2076}
2077
2078int start_output_stream(struct stream_out *out)
2079{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 struct audio_usecase *uc_info;
2082 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302083 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002085 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2086 ret = -EINVAL;
2087 goto error_config;
2088 }
2089
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302090 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2091 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2092 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302093
Naresh Tanniru80659832014-06-04 18:17:56 +05302094 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302095 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302096 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302097 goto error_config;
2098 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302099
Eric Laurentb23d5282013-05-14 15:27:20 -07002100 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 if (out->pcm_device_id < 0) {
2102 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2103 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002104 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002105 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 }
2107
2108 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002109
2110 if (!uc_info) {
2111 ret = -ENOMEM;
2112 goto error_config;
2113 }
2114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 uc_info->id = out->usecase;
2116 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002117 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002118 uc_info->devices = out->devices;
2119 uc_info->in_snd_device = SND_DEVICE_NONE;
2120 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002121 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302123 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2124 adev->perf_lock_opts,
2125 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302126
2127 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2128 audio_extn_keep_alive_stop();
2129 if (audio_extn_passthru_is_enabled() &&
2130 audio_extn_passthru_is_passthrough_stream(out)) {
2131 audio_extn_passthru_on_start(out);
2132 audio_extn_passthru_update_stream_configuration(adev, out);
2133 }
2134 }
2135
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002136 select_devices(adev, out->usecase);
2137
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002138 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2139 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002140 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002141 unsigned int flags = PCM_OUT;
2142 unsigned int pcm_open_retry_count = 0;
2143 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2144 flags |= PCM_MMAP | PCM_NOIRQ;
2145 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002146 } else if (out->realtime) {
2147 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002148 } else
2149 flags |= PCM_MONOTONIC;
2150
2151 while (1) {
2152 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2153 flags, &out->config);
2154 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2155 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2156 if (out->pcm != NULL) {
2157 pcm_close(out->pcm);
2158 out->pcm = NULL;
2159 }
2160 if (pcm_open_retry_count-- == 0) {
2161 ret = -EIO;
2162 goto error_open;
2163 }
2164 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2165 continue;
2166 }
2167 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002169
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002170 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2171 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002172
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002173 ALOGV("%s: pcm_prepare", __func__);
2174 if (pcm_is_ready(out->pcm)) {
2175 ret = pcm_prepare(out->pcm);
2176 if (ret < 0) {
2177 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2178 pcm_close(out->pcm);
2179 out->pcm = NULL;
2180 goto error_open;
2181 }
2182 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002184 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2185 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002187 out->compr = compress_open(adev->snd_card,
2188 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 COMPRESS_IN, &out->compr_config);
2190 if (out->compr && !is_compress_ready(out->compr)) {
2191 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2192 compress_close(out->compr);
2193 out->compr = NULL;
2194 ret = -EIO;
2195 goto error_open;
2196 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302197 /* compress_open sends params of the track, so reset the flag here */
2198 out->is_compr_metadata_avail = false;
2199
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 if (out->offload_callback)
2201 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002202
Fred Oh3f43e742015-03-04 18:42:34 -08002203 /* Since small bufs uses blocking writes, a write will be blocked
2204 for the default max poll time (20s) in the event of an SSR.
2205 Reduce the poll time to observe and deal with SSR faster.
2206 */
Ashish Jain5106d362016-05-11 19:23:33 +05302207 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002208 compress_set_max_poll_wait(out->compr, 1000);
2209 }
2210
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002211 audio_extn_dts_create_state_notifier_node(out->usecase);
2212 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2213 popcount(out->channel_mask),
2214 out->playback_started);
2215
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002216#ifdef DS1_DOLBY_DDP_ENABLED
2217 if (audio_extn_is_dolby_format(out->format))
2218 audio_extn_dolby_send_ddp_endp_params(adev);
2219#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302220 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002221 if (adev->visualizer_start_output != NULL)
2222 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2223 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302224 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002225 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002228
2229 if (ret == 0) {
2230 register_out_stream(out);
2231 if (out->realtime) {
2232 ret = pcm_start(out->pcm);
2233 if (ret < 0)
2234 goto error_open;
2235 }
2236 }
2237
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302238 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002239 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002240
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002241 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302243 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002245error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302246 /*
2247 * sleep 50ms to allow sufficient time for kernel
2248 * drivers to recover incases like SSR.
2249 */
2250 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002251 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252}
2253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254static int check_input_parameters(uint32_t sample_rate,
2255 audio_format_t format,
2256 int channel_count)
2257{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002258 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302260 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2261 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2262 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002263 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302264 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002265
2266 switch (channel_count) {
2267 case 1:
2268 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302269 case 3:
2270 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002271 case 6:
2272 break;
2273 default:
2274 ret = -EINVAL;
2275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276
2277 switch (sample_rate) {
2278 case 8000:
2279 case 11025:
2280 case 12000:
2281 case 16000:
2282 case 22050:
2283 case 24000:
2284 case 32000:
2285 case 44100:
2286 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302287 case 96000:
2288 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 break;
2290 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002291 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002292 }
2293
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002294 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295}
2296
2297static size_t get_input_buffer_size(uint32_t sample_rate,
2298 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002299 int channel_count,
2300 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301{
2302 size_t size = 0;
2303
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002304 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2305 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002307 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002308 if (is_low_latency)
2309 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302310
2311 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002313 /* make sure the size is multiple of 32 bytes
2314 * At 48 kHz mono 16-bit PCM:
2315 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2316 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2317 */
2318 size += 0x1f;
2319 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002320
2321 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322}
2323
Ashish Jain058165c2016-09-28 23:18:48 +05302324static size_t get_output_period_size(uint32_t sample_rate,
2325 audio_format_t format,
2326 int channel_count,
2327 int duration /*in millisecs*/)
2328{
2329 size_t size = 0;
2330 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2331
2332 if ((duration == 0) || (sample_rate == 0) ||
2333 (bytes_per_sample == 0) || (channel_count == 0)) {
2334 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2335 bytes_per_sample, channel_count);
2336 return -EINVAL;
2337 }
2338
2339 size = (sample_rate *
2340 duration *
2341 bytes_per_sample *
2342 channel_count) / 1000;
2343 /*
2344 * To have same PCM samples for all channels, the buffer size requires to
2345 * be multiple of (number of channels * bytes per sample)
2346 * For writes to succeed, the buffer must be written at address which is multiple of 32
2347 */
2348 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2349
2350 return (size/(channel_count * bytes_per_sample));
2351}
2352
Ashish Jain5106d362016-05-11 19:23:33 +05302353static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2354{
2355 uint64_t actual_frames_rendered = 0;
2356 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2357
2358 /* This adjustment accounts for buffering after app processor.
2359 * It is based on estimated DSP latency per use case, rather than exact.
2360 */
2361 int64_t platform_latency = platform_render_latency(out->usecase) *
2362 out->sample_rate / 1000000LL;
2363
2364 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2365 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2366 * hence only estimate.
2367 */
2368 int64_t signed_frames = out->written - kernel_buffer_size;
2369
2370 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2371
2372 if (signed_frames > 0)
2373 actual_frames_rendered = signed_frames;
2374
2375 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2376 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2377 (long long int)out->written, (int)kernel_buffer_size,
2378 audio_bytes_per_sample(out->compr_config.codec->format),
2379 popcount(out->channel_mask));
2380
2381 return actual_frames_rendered;
2382}
2383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2385{
2386 struct stream_out *out = (struct stream_out *)stream;
2387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389}
2390
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002391static int out_set_sample_rate(struct audio_stream *stream __unused,
2392 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393{
2394 return -ENOSYS;
2395}
2396
2397static size_t out_get_buffer_size(const struct audio_stream *stream)
2398{
2399 struct stream_out *out = (struct stream_out *)stream;
2400
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002401 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002403 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2404 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302405 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302406 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002407
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002408 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002409 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410}
2411
2412static uint32_t out_get_channels(const struct audio_stream *stream)
2413{
2414 struct stream_out *out = (struct stream_out *)stream;
2415
2416 return out->channel_mask;
2417}
2418
2419static audio_format_t out_get_format(const struct audio_stream *stream)
2420{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002421 struct stream_out *out = (struct stream_out *)stream;
2422
2423 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424}
2425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002426static int out_set_format(struct audio_stream *stream __unused,
2427 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428{
2429 return -ENOSYS;
2430}
2431
2432static int out_standby(struct audio_stream *stream)
2433{
2434 struct stream_out *out = (struct stream_out *)stream;
2435 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302437 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2438 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002440 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002442 if (adev->adm_deregister_stream)
2443 adev->adm_deregister_stream(adev->adm_data, out->handle);
2444
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002445 if (is_offload_usecase(out->usecase))
2446 stop_compressed_output_l(out);
2447
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002448 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002450 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2451 voice_extn_compress_voip_close_output_stream(stream);
2452 pthread_mutex_unlock(&adev->lock);
2453 pthread_mutex_unlock(&out->lock);
2454 ALOGD("VOIP output entered standby");
2455 return 0;
2456 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 if (out->pcm) {
2458 pcm_close(out->pcm);
2459 out->pcm = NULL;
2460 }
2461 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002462 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302463 out->send_next_track_params = false;
2464 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002465 out->gapless_mdata.encoder_delay = 0;
2466 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002467 if (out->compr != NULL) {
2468 compress_close(out->compr);
2469 out->compr = NULL;
2470 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002473 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 }
2475 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302476 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 return 0;
2478}
2479
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002480static int out_dump(const struct audio_stream *stream __unused,
2481 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482{
2483 return 0;
2484}
2485
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002486static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2487{
2488 int ret = 0;
2489 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002490
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002491 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002492 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002493 return -EINVAL;
2494 }
2495
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302496 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002497
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002498 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2499 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302500 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002501 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002502 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2503 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302504 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002505 }
2506
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002507 ALOGV("%s new encoder delay %u and padding %u", __func__,
2508 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2509
2510 return 0;
2511}
2512
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002513static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2514{
2515 return out == adev->primary_output || out == adev->voice_tx_output;
2516}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2519{
2520 struct stream_out *out = (struct stream_out *)stream;
2521 struct audio_device *adev = out->dev;
2522 struct str_parms *parms;
2523 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002524 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525
sangwoobc677242013-08-08 16:53:43 +09002526 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002527 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302529 if (!parms)
2530 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002531 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2532 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002534 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002535 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002538 * When HDMI cable is unplugged the music playback is paused and
2539 * the policy manager sends routing=0. But the audioflinger continues
2540 * to write data until standby time (3sec). As the HDMI core is
2541 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002542 * Avoid this by routing audio to speaker until standby.
2543 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002544 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2545 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302546 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002547 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2548 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002549 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302550 /*
2551 * When A2DP is disconnected the
2552 * music playback is paused and the policy manager sends routing=0
2553 * But the audioflingercontinues to write data until standby time
2554 * (3sec). As BT is turned off, the write gets blocked.
2555 * Avoid this by routing audio to speaker until standby.
2556 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002557 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302558 (val == AUDIO_DEVICE_NONE)) {
2559 val = AUDIO_DEVICE_OUT_SPEAKER;
2560 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302561 /* To avoid a2dp to sco overlapping force route BT usecases
2562 * to speaker based on Phone state
2563 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002564 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302565 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2566 (adev->mode == AUDIO_MODE_IN_CALL))) {
2567 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2568 val = AUDIO_DEVICE_OUT_SPEAKER;
2569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002570 /*
2571 * select_devices() call below switches all the usecases on the same
2572 * backend to the new device. Refer to check_usecases_codec_backend() in
2573 * the select_devices(). But how do we undo this?
2574 *
2575 * For example, music playback is active on headset (deep-buffer usecase)
2576 * and if we go to ringtones and select a ringtone, low-latency usecase
2577 * will be started on headset+speaker. As we can't enable headset+speaker
2578 * and headset devices at the same time, select_devices() switches the music
2579 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2580 * So when the ringtone playback is completed, how do we undo the same?
2581 *
2582 * We are relying on the out_set_parameters() call on deep-buffer output,
2583 * once the ringtone playback is ended.
2584 * NOTE: We should not check if the current devices are same as new devices.
2585 * Because select_devices() must be called to switch back the music
2586 * playback to headset.
2587 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002588 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002589 audio_devices_t new_dev = val;
2590 bool same_dev = out->devices == new_dev;
2591 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002592
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002593 if (output_drives_call(adev, out)) {
2594 if(!voice_is_in_call(adev)) {
2595 if (adev->mode == AUDIO_MODE_IN_CALL) {
2596 adev->current_call_output = out;
2597 ret = voice_start_call(adev);
2598 }
2599 } else {
2600 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002601 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002602 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002603 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002604
2605 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002606 if (!same_dev) {
2607 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302608 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2609 adev->perf_lock_opts,
2610 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002611 if (adev->adm_on_routing_change)
2612 adev->adm_on_routing_change(adev->adm_data,
2613 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002614 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002615 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302616 if (!same_dev)
2617 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002618 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002619 }
2620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002622 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002624
2625 if (out == adev->primary_output) {
2626 pthread_mutex_lock(&adev->lock);
2627 audio_extn_set_parameters(adev, parms);
2628 pthread_mutex_unlock(&adev->lock);
2629 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002630 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002631 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002632 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002633
2634 audio_extn_dts_create_state_notifier_node(out->usecase);
2635 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2636 popcount(out->channel_mask),
2637 out->playback_started);
2638
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002639 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002640 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002641
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302642 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2643 if (err >= 0) {
2644 strlcpy(out->profile, value, sizeof(out->profile));
2645 ALOGV("updating stream profile with value '%s'", out->profile);
2646 lock_output_stream(out);
2647 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2648 &adev->streams_output_cfg_list,
2649 out->devices, out->flags, out->format,
2650 out->sample_rate, out->bit_width,
2651 out->channel_mask, out->profile,
2652 &out->app_type_cfg);
2653 pthread_mutex_unlock(&out->lock);
2654 }
2655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302657error:
Eric Laurent994a6932013-07-17 11:51:42 -07002658 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 return ret;
2660}
2661
2662static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2663{
2664 struct stream_out *out = (struct stream_out *)stream;
2665 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002666 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 char value[256];
2668 struct str_parms *reply = str_parms_create();
2669 size_t i, j;
2670 int ret;
2671 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002672
2673 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002674 if (reply) {
2675 str_parms_destroy(reply);
2676 }
2677 if (query) {
2678 str_parms_destroy(query);
2679 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002680 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2681 return NULL;
2682 }
2683
Eric Laurent994a6932013-07-17 11:51:42 -07002684 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2686 if (ret >= 0) {
2687 value[0] = '\0';
2688 i = 0;
2689 while (out->supported_channel_masks[i] != 0) {
2690 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2691 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2692 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002693 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002695 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 first = false;
2697 break;
2698 }
2699 }
2700 i++;
2701 }
2702 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2703 str = str_parms_to_str(reply);
2704 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002705 voice_extn_out_get_parameters(out, query, reply);
2706 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002707 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002708 free(str);
2709 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002712
Alexy Joseph62142aa2015-11-16 15:10:34 -08002713
2714 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2715 if (ret >= 0) {
2716 value[0] = '\0';
2717 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2718 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302719 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002720 } else {
2721 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302722 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002723 }
2724 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002725 if (str)
2726 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002727 str = str_parms_to_str(reply);
2728 }
2729
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002730 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2731 if (ret >= 0) {
2732 value[0] = '\0';
2733 i = 0;
2734 first = true;
2735 while (out->supported_formats[i] != 0) {
2736 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2737 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2738 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002739 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002740 }
2741 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2742 first = false;
2743 break;
2744 }
2745 }
2746 i++;
2747 }
2748 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002749 if (str)
2750 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002751 str = str_parms_to_str(reply);
2752 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002753
2754 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2755 if (ret >= 0) {
2756 value[0] = '\0';
2757 i = 0;
2758 first = true;
2759 while (out->supported_sample_rates[i] != 0) {
2760 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2761 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2762 if (!first) {
2763 strlcat(value, "|", sizeof(value));
2764 }
2765 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2766 first = false;
2767 break;
2768 }
2769 }
2770 i++;
2771 }
2772 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2773 if (str)
2774 free(str);
2775 str = str_parms_to_str(reply);
2776 }
2777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 str_parms_destroy(query);
2779 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002780 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 return str;
2782}
2783
2784static uint32_t out_get_latency(const struct audio_stream_out *stream)
2785{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002786 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002788 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789
Alexy Josephaa54c872014-12-03 02:46:47 -08002790 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002791 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002792 } else if (out->realtime) {
2793 // since the buffer won't be filled up faster than realtime,
2794 // return a smaller number
2795 if (out->config.rate)
2796 period_ms = (out->af_period_multiplier * out->config.period_size *
2797 1000) / (out->config.rate);
2798 else
2799 period_ms = 0;
2800 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002801 } else {
2802 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002803 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002804 }
2805
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302806 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002807 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808}
2809
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302810static float AmpToDb(float amplification)
2811{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302812 float db = DSD_VOLUME_MIN_DB;
2813 if (amplification > 0) {
2814 db = 20 * log10(amplification);
2815 if(db < DSD_VOLUME_MIN_DB)
2816 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302817 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302818 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302819}
2820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821static int out_set_volume(struct audio_stream_out *stream, float left,
2822 float right)
2823{
Eric Laurenta9024de2013-04-04 09:19:12 -07002824 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 int volume[2];
2826
Eric Laurenta9024de2013-04-04 09:19:12 -07002827 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2828 /* only take left channel into account: the API is for stereo anyway */
2829 out->muted = (left == 0.0f);
2830 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002831 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302832 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002833 /*
2834 * Set mute or umute on HDMI passthrough stream.
2835 * Only take left channel into account.
2836 * Mute is 0 and unmute 1
2837 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302838 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302839 } else if (out->format == AUDIO_FORMAT_DSD){
2840 char mixer_ctl_name[128] = "DSD Volume";
2841 struct audio_device *adev = out->dev;
2842 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2843
2844 if (!ctl) {
2845 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2846 __func__, mixer_ctl_name);
2847 return -EINVAL;
2848 }
2849 volume[0] = (int)(AmpToDb(left));
2850 volume[1] = (int)(AmpToDb(right));
2851 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2852 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002853 } else {
2854 char mixer_ctl_name[128];
2855 struct audio_device *adev = out->dev;
2856 struct mixer_ctl *ctl;
2857 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002858 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002860 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2861 "Compress Playback %d Volume", pcm_device_id);
2862 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2863 if (!ctl) {
2864 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2865 __func__, mixer_ctl_name);
2866 return -EINVAL;
2867 }
2868 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2869 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2870 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2871 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002873 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 return -ENOSYS;
2876}
2877
2878static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2879 size_t bytes)
2880{
2881 struct stream_out *out = (struct stream_out *)stream;
2882 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302883 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002884 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002886 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302887
Naresh Tanniru80659832014-06-04 18:17:56 +05302888 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002889
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302890 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302891 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302892 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2893 pthread_mutex_unlock(&out->lock);
2894 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302895 } else {
2896 /* increase written size during SSR to avoid mismatch
2897 * with the written frames count in AF
2898 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002899 // bytes per frame
2900 size_t bpf = audio_bytes_per_sample(out->format) *
2901 audio_channel_count_from_out_mask(out->channel_mask);
2902 if (bpf != 0)
2903 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302904 ALOGD(" %s: sound card is not active/SSR state", __func__);
2905 ret= -EIO;
2906 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302907 }
2908 }
2909
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302910 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302911 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2912 if (audio_bytes_per_sample(out->format) != 0)
2913 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2914 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302915 goto exit;
2916 }
2917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002919 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002920 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002921 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2922 ret = voice_extn_compress_voip_start_output_stream(out);
2923 else
2924 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002925 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002926 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002928 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 goto exit;
2930 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002931
2932 if (last_known_cal_step != -1) {
2933 ALOGD("%s: retry previous failed cal level set", __func__);
2934 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2935 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937
Ashish Jain81eb2a82015-05-13 10:52:34 +05302938 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002939 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302940 adev->is_channel_status_set = true;
2941 }
2942
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002943 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002944 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002945 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002946 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002947 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2948 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302949 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2950 ALOGD("copl(%p):send next track params in gapless", out);
2951 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2952 out->send_next_track_params = false;
2953 out->is_compr_metadata_avail = false;
2954 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002955 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302956 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302957 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002958
Ashish Jain83a6cc22016-06-28 14:34:17 +05302959 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302960 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302961 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302962 pthread_mutex_unlock(&out->lock);
2963 return -EINVAL;
2964 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302965 audio_format_t dst_format = out->hal_op_format;
2966 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302967
2968 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2969 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2970
Ashish Jain83a6cc22016-06-28 14:34:17 +05302971 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302972 dst_format,
2973 buffer,
2974 src_format,
2975 frames);
2976
Ashish Jain83a6cc22016-06-28 14:34:17 +05302977 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302978 bytes_to_write);
2979
2980 /*Convert written bytes in audio flinger format*/
2981 if (ret > 0)
2982 ret = ((ret * format_to_bitwidth_table[out->format]) /
2983 format_to_bitwidth_table[dst_format]);
2984 }
2985 } else
2986 ret = compress_write(out->compr, buffer, bytes);
2987
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302988 if (ret < 0)
2989 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302990 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302991 /*msg to cb thread only if non blocking write is enabled*/
2992 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302993 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302995 } else if (-ENETRESET == ret) {
2996 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2997 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2998 pthread_mutex_unlock(&out->lock);
2999 out_standby(&out->stream.common);
3000 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 }
Ashish Jain5106d362016-05-11 19:23:33 +05303002 if ( ret == (ssize_t)bytes && !out->non_blocking)
3003 out->written += bytes;
3004
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303005 /* Call compr start only when non-zero bytes of data is there to be rendered */
3006 if (!out->playback_started && ret > 0) {
3007 int status = compress_start(out->compr);
3008 if (status < 0) {
3009 ret = status;
3010 ALOGE("%s: compr start failed with err %d", __func__, errno);
3011 goto exit;
3012 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003013 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003014 out->playback_started = 1;
3015 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003016
3017 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3018 popcount(out->channel_mask),
3019 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 }
3021 pthread_mutex_unlock(&out->lock);
3022 return ret;
3023 } else {
3024 if (out->pcm) {
3025 if (out->muted)
3026 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003027
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303028 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003029
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003030 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003031
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003032 if (out->config.rate)
3033 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3034 out->config.rate;
3035
3036 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3037
3038 request_out_focus(out, ns);
3039
3040 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003041 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003042 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303043 out->convert_buffer != NULL) {
3044
3045 memcpy_by_audio_format(out->convert_buffer,
3046 out->hal_op_format,
3047 buffer,
3048 out->hal_ip_format,
3049 out->config.period_size * out->config.channels);
3050
3051 ret = pcm_write(out->pcm, out->convert_buffer,
3052 (out->config.period_size *
3053 out->config.channels *
3054 format_to_bitwidth_table[out->hal_op_format]));
3055 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003056 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303057 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003058
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003059 release_out_focus(out);
3060
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303061 if (ret < 0)
3062 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303063 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3064 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3065 else
3066 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 }
3069
3070exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303071 /* ToDo: There may be a corner case when SSR happens back to back during
3072 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303073 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303074 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303075 }
3076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 pthread_mutex_unlock(&out->lock);
3078
3079 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003080 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003081 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303082 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303083 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303084 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303085 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303086 out->standby = true;
3087 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303089 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3090 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3091 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 }
3093 return bytes;
3094}
3095
3096static int out_get_render_position(const struct audio_stream_out *stream,
3097 uint32_t *dsp_frames)
3098{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003099 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303100 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003101
3102 if (dsp_frames == NULL)
3103 return -EINVAL;
3104
3105 *dsp_frames = 0;
3106 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003107 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303108
3109 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3110 * this operation and adev_close_output_stream(where out gets reset).
3111 */
3112 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3113 *dsp_frames = get_actual_pcm_frames_rendered(out);
3114 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3115 return 0;
3116 }
3117
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003118 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303119 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303120 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303122 if (ret < 0)
3123 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303125 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003126 }
3127 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303128 if (-ENETRESET == ret) {
3129 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3130 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3131 return -EINVAL;
3132 } else if(ret < 0) {
3133 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3134 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303135 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3136 /*
3137 * Handle corner case where compress session is closed during SSR
3138 * and timestamp is queried
3139 */
3140 ALOGE(" ERROR: sound card not active, return error");
3141 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303142 } else {
3143 return 0;
3144 }
Zhou Song32a556e2015-05-05 10:46:56 +08003145 } else if (audio_is_linear_pcm(out->format)) {
3146 *dsp_frames = out->written;
3147 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 } else
3149 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150}
3151
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003152static int out_add_audio_effect(const struct audio_stream *stream __unused,
3153 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154{
3155 return 0;
3156}
3157
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003158static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3159 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160{
3161 return 0;
3162}
3163
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003164static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3165 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166{
3167 return -EINVAL;
3168}
3169
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003170static int out_get_presentation_position(const struct audio_stream_out *stream,
3171 uint64_t *frames, struct timespec *timestamp)
3172{
3173 struct stream_out *out = (struct stream_out *)stream;
3174 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003175 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003176
Ashish Jain5106d362016-05-11 19:23:33 +05303177 /* below piece of code is not guarded against any lock because audioFliner serializes
3178 * this operation and adev_close_output_stream( where out gets reset).
3179 */
3180 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3181 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3182 *frames = get_actual_pcm_frames_rendered(out);
3183 /* this is the best we can do */
3184 clock_gettime(CLOCK_MONOTONIC, timestamp);
3185 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3186 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3187 return 0;
3188 }
3189
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003190 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003191
Ashish Jain5106d362016-05-11 19:23:33 +05303192 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3193 ret = compress_get_tstamp(out->compr, &dsp_frames,
3194 &out->sample_rate);
3195 ALOGVV("%s rendered frames %ld sample_rate %d",
3196 __func__, dsp_frames, out->sample_rate);
3197 *frames = dsp_frames;
3198 if (ret < 0)
3199 ret = -errno;
3200 if (-ENETRESET == ret) {
3201 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3202 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3203 ret = -EINVAL;
3204 } else
3205 ret = 0;
3206 /* this is the best we can do */
3207 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003208 } else {
3209 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003210 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003211 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3212 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003213 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003214 // This adjustment accounts for buffering after app processor.
3215 // It is based on estimated DSP latency per use case, rather than exact.
3216 signed_frames -=
3217 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3218
Eric Laurent949a0892013-09-20 09:20:13 -07003219 // It would be unusual for this value to be negative, but check just in case ...
3220 if (signed_frames >= 0) {
3221 *frames = signed_frames;
3222 ret = 0;
3223 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003224 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303225 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3226 *frames = out->written;
3227 clock_gettime(CLOCK_MONOTONIC, timestamp);
3228 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003229 }
3230 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003231 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003232 return ret;
3233}
3234
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235static int out_set_callback(struct audio_stream_out *stream,
3236 stream_callback_t callback, void *cookie)
3237{
3238 struct stream_out *out = (struct stream_out *)stream;
3239
3240 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003241 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003242 out->offload_callback = callback;
3243 out->offload_cookie = cookie;
3244 pthread_mutex_unlock(&out->lock);
3245 return 0;
3246}
3247
3248static int out_pause(struct audio_stream_out* stream)
3249{
3250 struct stream_out *out = (struct stream_out *)stream;
3251 int status = -ENOSYS;
3252 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003253 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003254 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003255 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303257 struct audio_device *adev = out->dev;
3258 int snd_scard_state = get_snd_card_state(adev);
3259
3260 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3261 status = compress_pause(out->compr);
3262
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003264
Mingming Yin21854652016-04-13 11:54:02 -07003265 if (audio_extn_passthru_is_active()) {
3266 ALOGV("offload use case, pause passthru");
3267 audio_extn_passthru_on_pause(out);
3268 }
3269
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303270 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003271 audio_extn_dts_notify_playback_state(out->usecase, 0,
3272 out->sample_rate, popcount(out->channel_mask),
3273 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 }
3275 pthread_mutex_unlock(&out->lock);
3276 }
3277 return status;
3278}
3279
3280static int out_resume(struct audio_stream_out* stream)
3281{
3282 struct stream_out *out = (struct stream_out *)stream;
3283 int status = -ENOSYS;
3284 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003285 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003286 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003288 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303290 struct audio_device *adev = out->dev;
3291 int snd_scard_state = get_snd_card_state(adev);
3292
Mingming Yin21854652016-04-13 11:54:02 -07003293 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3294 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3295 pthread_mutex_lock(&out->dev->lock);
3296 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003297 pthread_mutex_unlock(&out->dev->lock);
3298 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303299 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003300 }
3301 if (!status) {
3302 out->offload_state = OFFLOAD_STATE_PLAYING;
3303 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303304 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003305 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3306 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307 }
3308 pthread_mutex_unlock(&out->lock);
3309 }
3310 return status;
3311}
3312
3313static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3314{
3315 struct stream_out *out = (struct stream_out *)stream;
3316 int status = -ENOSYS;
3317 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003318 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003319 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003320 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3321 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3322 else
3323 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3324 pthread_mutex_unlock(&out->lock);
3325 }
3326 return status;
3327}
3328
3329static int out_flush(struct audio_stream_out* stream)
3330{
3331 struct stream_out *out = (struct stream_out *)stream;
3332 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003333 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003334 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003335 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003336 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3337 stop_compressed_output_l(out);
3338 out->written = 0;
3339 } else {
3340 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3341 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003343 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003344 return 0;
3345 }
3346 return -ENOSYS;
3347}
3348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349/** audio_stream_in implementation **/
3350static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3351{
3352 struct stream_in *in = (struct stream_in *)stream;
3353
3354 return in->config.rate;
3355}
3356
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003357static int in_set_sample_rate(struct audio_stream *stream __unused,
3358 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359{
3360 return -ENOSYS;
3361}
3362
3363static size_t in_get_buffer_size(const struct audio_stream *stream)
3364{
3365 struct stream_in *in = (struct stream_in *)stream;
3366
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003367 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3368 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003369 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3370 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303371 else if(audio_extn_cin_attached_usecase(in->usecase))
3372 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003373
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003374 return in->config.period_size * in->af_period_multiplier *
3375 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376}
3377
3378static uint32_t in_get_channels(const struct audio_stream *stream)
3379{
3380 struct stream_in *in = (struct stream_in *)stream;
3381
3382 return in->channel_mask;
3383}
3384
3385static audio_format_t in_get_format(const struct audio_stream *stream)
3386{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003387 struct stream_in *in = (struct stream_in *)stream;
3388
3389 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390}
3391
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003392static int in_set_format(struct audio_stream *stream __unused,
3393 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394{
3395 return -ENOSYS;
3396}
3397
3398static int in_standby(struct audio_stream *stream)
3399{
3400 struct stream_in *in = (struct stream_in *)stream;
3401 struct audio_device *adev = in->dev;
3402 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303403 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3404 stream, in->usecase, use_case_table[in->usecase]);
3405
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003406 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003407 if (!in->standby && in->is_st_session) {
3408 ALOGD("%s: sound trigger pcm stop lab", __func__);
3409 audio_extn_sound_trigger_stop_lab(in);
3410 in->standby = 1;
3411 }
3412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003414 if (adev->adm_deregister_stream)
3415 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3416
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003417 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003419 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3420 voice_extn_compress_voip_close_input_stream(stream);
3421 ALOGD("VOIP input entered standby");
3422 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303423 if (audio_extn_cin_attached_usecase(in->usecase))
3424 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003425 if (in->pcm) {
3426 pcm_close(in->pcm);
3427 in->pcm = NULL;
3428 }
3429 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003430 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003431 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 }
3433 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003434 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 return status;
3436}
3437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003438static int in_dump(const struct audio_stream *stream __unused,
3439 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
3441 return 0;
3442}
3443
3444static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3445{
3446 struct stream_in *in = (struct stream_in *)stream;
3447 struct audio_device *adev = in->dev;
3448 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003450 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303452 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 parms = str_parms_create_str(kvpairs);
3454
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303455 if (!parms)
3456 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003457 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003458 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003459
3460 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3461 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 val = atoi(value);
3463 /* no audio source uses val == 0 */
3464 if ((in->source != val) && (val != 0)) {
3465 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003466 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3467 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3468 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003469 (in->config.rate == 8000 || in->config.rate == 16000 ||
3470 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003471 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003472 err = voice_extn_compress_voip_open_input_stream(in);
3473 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003474 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003475 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003476 }
3477 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478 }
3479 }
3480
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003481 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3482 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003484 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 in->device = val;
3486 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003487 if (!in->standby && !in->is_st_session) {
3488 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003489 if (adev->adm_on_routing_change)
3490 adev->adm_on_routing_change(adev->adm_data,
3491 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003492 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 }
3495 }
3496
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303497 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3498 if (err >= 0) {
3499 strlcpy(in->profile, value, sizeof(in->profile));
3500 ALOGV("updating stream profile with value '%s'", in->profile);
3501 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3502 &adev->streams_input_cfg_list,
3503 in->device, in->flags, in->format,
3504 in->sample_rate, in->bit_width,
3505 in->profile, &in->app_type_cfg);
3506 }
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003509 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
3511 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303512error:
Eric Laurent994a6932013-07-17 11:51:42 -07003513 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 return ret;
3515}
3516
3517static char* in_get_parameters(const struct audio_stream *stream,
3518 const char *keys)
3519{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003520 struct stream_in *in = (struct stream_in *)stream;
3521 struct str_parms *query = str_parms_create_str(keys);
3522 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003523 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003524
3525 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003526 if (reply) {
3527 str_parms_destroy(reply);
3528 }
3529 if (query) {
3530 str_parms_destroy(query);
3531 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003532 ALOGE("in_get_parameters: failed to create query or reply");
3533 return NULL;
3534 }
3535
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003536 ALOGV("%s: enter: keys - %s", __func__, keys);
3537
3538 voice_extn_in_get_parameters(in, query, reply);
3539
3540 str = str_parms_to_str(reply);
3541 str_parms_destroy(query);
3542 str_parms_destroy(reply);
3543
3544 ALOGV("%s: exit: returns - %s", __func__, str);
3545 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546}
3547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003548static int in_set_gain(struct audio_stream_in *stream __unused,
3549 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550{
3551 return 0;
3552}
3553
3554static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3555 size_t bytes)
3556{
3557 struct stream_in *in = (struct stream_in *)stream;
3558 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303559 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303560 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303561 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003563 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303564
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003565 if (in->is_st_session) {
3566 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3567 /* Read from sound trigger HAL */
3568 audio_extn_sound_trigger_read(in, buffer, bytes);
3569 pthread_mutex_unlock(&in->lock);
3570 return bytes;
3571 }
3572
Ashish Jainbbce4322016-02-16 13:25:27 +05303573 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003574 ALOGD(" %s: sound card is not active/SSR state", __func__);
3575 ret= -EIO;;
3576 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303577 }
3578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003580 pthread_mutex_lock(&adev->lock);
3581 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3582 ret = voice_extn_compress_voip_start_input_stream(in);
3583 else
3584 ret = start_input_stream(in);
3585 pthread_mutex_unlock(&adev->lock);
3586 if (ret != 0) {
3587 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 }
3589 in->standby = 0;
3590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003592 // what's the duration requested by the client?
3593 long ns = 0;
3594
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303595 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003596 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3597 in->config.rate;
3598
3599 request_in_focus(in, ns);
3600 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003601
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303602 if (audio_extn_cin_attached_usecase(in->usecase)) {
3603 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3604 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303605 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003606 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303607 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003608 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003609 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003610 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303611 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003612 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303613 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3614 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3615 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3616 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303617 ret = -EINVAL;
3618 goto exit;
3619 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303620 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303621 ret = -errno;
3622 }
3623 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303624 /* bytes read is always set to bytes for non compress usecases */
3625 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 }
3627
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003628 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 /*
3631 * Instead of writing zeroes here, we could trust the hardware
3632 * to always provide zeroes when muted.
3633 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303634 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3635 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 memset(buffer, 0, bytes);
3637
3638exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303639 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303640 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003641 if (-ENETRESET == ret)
3642 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 pthread_mutex_unlock(&in->lock);
3645
3646 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303647 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303648 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303649 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303650 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303651 in->standby = true;
3652 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303653 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003655 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303656 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303657 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303659 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660}
3661
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003662static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663{
3664 return 0;
3665}
3666
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003667static int add_remove_audio_effect(const struct audio_stream *stream,
3668 effect_handle_t effect,
3669 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003671 struct stream_in *in = (struct stream_in *)stream;
3672 int status = 0;
3673 effect_descriptor_t desc;
3674
3675 status = (*effect)->get_descriptor(effect, &desc);
3676 if (status != 0)
3677 return status;
3678
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003679 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003680 pthread_mutex_lock(&in->dev->lock);
3681 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3682 in->enable_aec != enable &&
3683 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3684 in->enable_aec = enable;
3685 if (!in->standby)
3686 select_devices(in->dev, in->usecase);
3687 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003688 if (in->enable_ns != enable &&
3689 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3690 in->enable_ns = enable;
3691 if (!in->standby)
3692 select_devices(in->dev, in->usecase);
3693 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003694 pthread_mutex_unlock(&in->dev->lock);
3695 pthread_mutex_unlock(&in->lock);
3696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 return 0;
3698}
3699
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003700static int in_add_audio_effect(const struct audio_stream *stream,
3701 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702{
Eric Laurent994a6932013-07-17 11:51:42 -07003703 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003704 return add_remove_audio_effect(stream, effect, true);
3705}
3706
3707static int in_remove_audio_effect(const struct audio_stream *stream,
3708 effect_handle_t effect)
3709{
Eric Laurent994a6932013-07-17 11:51:42 -07003710 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003711 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712}
3713
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303714int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 audio_io_handle_t handle,
3716 audio_devices_t devices,
3717 audio_output_flags_t flags,
3718 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003719 struct audio_stream_out **stream_out,
3720 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721{
3722 struct audio_device *adev = (struct audio_device *)dev;
3723 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303724 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003725 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303728
3729 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3730 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003731 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303732 return -EINVAL;
3733 }
3734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3736
Mingming Yin3a941d42016-02-17 18:08:05 -08003737 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3738 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303739 devices, flags, &out->stream);
3740
3741
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003742 if (!out) {
3743 return -ENOMEM;
3744 }
3745
Haynes Mathew George204045b2015-02-25 20:32:03 -08003746 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003747 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003748 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 if (devices == AUDIO_DEVICE_NONE)
3751 devices = AUDIO_DEVICE_OUT_SPEAKER;
3752
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 out->flags = flags;
3754 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003755 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003756 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003757 out->sample_rate = config->sample_rate;
3758 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3759 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003760 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003761 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003762 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303763 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764
Mingming Yin3a941d42016-02-17 18:08:05 -08003765 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3766 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3767 pthread_mutex_lock(&adev->lock);
3768 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3769 ret = read_hdmi_sink_caps(out);
3770 pthread_mutex_unlock(&adev->lock);
3771 if (ret != 0) {
3772 if (ret == -ENOSYS) {
3773 /* ignore and go with default */
3774 ret = 0;
3775 } else {
3776 ALOGE("error reading hdmi sink caps");
3777 goto error_open;
3778 }
3779 }
3780 }
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003783 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303784 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3785 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003786 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3787 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3788
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003789 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003790 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3791 /*
3792 * Do not handle stereo output in Multi-channel cases
3793 * Stereo case is handled in normal playback path
3794 */
3795 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3796 ret = AUDIO_CHANNEL_OUT_STEREO;
3797 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003798
3799 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3800 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003801 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003802 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003803 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003804
3805 if (config->sample_rate == 0)
3806 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3807 if (config->channel_mask == 0)
3808 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003809 if (config->format == 0)
3810 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003811
3812 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003813 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003814 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3816 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003818 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003820 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3821 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003822 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003823 ret = voice_extn_compress_voip_open_output_stream(out);
3824 if (ret != 0) {
3825 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3826 __func__, ret);
3827 goto error_open;
3828 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003829 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3830 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003832 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3833 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3834 ALOGE("%s: Unsupported Offload information", __func__);
3835 ret = -EINVAL;
3836 goto error_open;
3837 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003838
Mingming Yin3a941d42016-02-17 18:08:05 -08003839 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003840 if(config->offload_info.format == 0)
3841 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003842 if (config->offload_info.sample_rate == 0)
3843 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003844 }
3845
Mingming Yin90310102013-11-13 16:57:00 -08003846 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303847 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003848 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003849 ret = -EINVAL;
3850 goto error_open;
3851 }
3852
3853 out->compr_config.codec = (struct snd_codec *)
3854 calloc(1, sizeof(struct snd_codec));
3855
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003856 if (!out->compr_config.codec) {
3857 ret = -ENOMEM;
3858 goto error_open;
3859 }
3860
vivek mehta0ea887a2015-08-26 14:01:20 -07003861 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303862 out->stream.pause = out_pause;
3863 out->stream.flush = out_flush;
3864 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003865 out->usecase = get_offload_usecase(adev, true);
3866 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003867 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003868 out->stream.set_callback = out_set_callback;
3869 out->stream.pause = out_pause;
3870 out->stream.resume = out_resume;
3871 out->stream.drain = out_drain;
3872 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003873 out->usecase = get_offload_usecase(adev, false);
3874 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003875 }
vivek mehta446c3962015-09-14 10:57:35 -07003876
3877 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003878 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3879 config->format == 0 && config->sample_rate == 0 &&
3880 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003881 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003882 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3883 } else {
3884 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3885 ret = -EEXIST;
3886 goto error_open;
3887 }
vivek mehta446c3962015-09-14 10:57:35 -07003888 }
3889
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003890 if (config->offload_info.channel_mask)
3891 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003892 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003893 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003894 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003895 } else {
3896 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3897 ret = -EINVAL;
3898 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003899 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003900
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003901 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 out->sample_rate = config->offload_info.sample_rate;
3903
Mingming Yin3ee55c62014-08-04 14:23:35 -07003904 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003905
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303906 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3907 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3908 audio_extn_dolby_send_ddp_endp_params(adev);
3909 audio_extn_dolby_set_dmid(adev);
3910 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003911
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003912 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003913 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003914 out->compr_config.codec->bit_rate =
3915 config->offload_info.bit_rate;
3916 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303917 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003918 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303919 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003920 /*TODO: Do we need to change it for passthrough */
3921 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003922
Manish Dewangana6fc5442015-08-24 20:30:31 +05303923 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3924 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3925 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3926 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303927
3928 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3929 AUDIO_FORMAT_PCM) {
3930
3931 /*Based on platform support, configure appropriate alsa format for corresponding
3932 *hal input format.
3933 */
3934 out->compr_config.codec->format = hal_format_to_alsa(
3935 config->offload_info.format);
3936
Ashish Jain83a6cc22016-06-28 14:34:17 +05303937 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303938 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303939 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303940
3941 /*for direct PCM playback populate bit_width based on selected alsa format as
3942 *hal input format and alsa format might differ based on platform support.
3943 */
3944 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303945 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303946
3947 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3948
3949 /* Check if alsa session is configured with the same format as HAL input format,
3950 * if not then derive correct fragment size needed to accomodate the
3951 * conversion of HAL input format to alsa format.
3952 */
3953 audio_extn_utils_update_direct_pcm_fragment_size(out);
3954
3955 /*if hal input and output fragment size is different this indicates HAL input format is
3956 *not same as the alsa format
3957 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303958 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303959 /*Allocate a buffer to convert input data to the alsa configured format.
3960 *size of convert buffer is equal to the size required to hold one fragment size
3961 *worth of pcm data, this is because flinger does not write more than fragment_size
3962 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303963 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3964 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303965 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3966 ret = -ENOMEM;
3967 goto error_open;
3968 }
3969 }
3970 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3971 out->compr_config.fragment_size =
3972 audio_extn_passthru_get_buffer_size(&config->offload_info);
3973 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3974 } else {
3975 out->compr_config.fragment_size =
3976 platform_get_compress_offload_buffer_size(&config->offload_info);
3977 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3978 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003979
Amit Shekhar6f461b12014-08-01 14:52:58 -07003980 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303981 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3984 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003985
Alexy Josephaa54c872014-12-03 02:46:47 -08003986
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003987 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303988 out->send_next_track_params = false;
3989 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003990 out->offload_state = OFFLOAD_STATE_IDLE;
3991 out->playback_started = 0;
3992
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003993 audio_extn_dts_create_state_notifier_node(out->usecase);
3994
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3996 __func__, config->offload_info.version,
3997 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303998
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303999 /* Check if DSD audio format is supported in codec
4000 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304001 */
4002
4003 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304004 (!platform_check_codec_dsd_support(adev->platform) ||
4005 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304006 ret = -EINVAL;
4007 goto error_open;
4008 }
4009
Ashish Jain5106d362016-05-11 19:23:33 +05304010 /* Disable gapless if any of the following is true
4011 * passthrough playback
4012 * AV playback
4013 * Direct PCM playback
4014 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304015 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304016 (config->format == AUDIO_FORMAT_DSD) ||
4017 config->offload_info.has_video ||
4018 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304019 check_and_set_gapless_mode(adev, false);
4020 } else
4021 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004022
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304023 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004024 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4025 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304026 if (config->format == AUDIO_FORMAT_DSD) {
4027 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4028 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4029 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004030
4031 create_offload_callback_thread(out);
4032
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004033 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304034 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004035 if (ret != 0) {
4036 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4037 __func__, ret);
4038 goto error_open;
4039 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004040 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4041 if (config->sample_rate == 0)
4042 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4043 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4044 config->sample_rate != 8000) {
4045 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4046 ret = -EINVAL;
4047 goto error_open;
4048 }
4049 out->sample_rate = config->sample_rate;
4050 out->config.rate = config->sample_rate;
4051 if (config->format == AUDIO_FORMAT_DEFAULT)
4052 config->format = AUDIO_FORMAT_PCM_16_BIT;
4053 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4054 config->format = AUDIO_FORMAT_PCM_16_BIT;
4055 ret = -EINVAL;
4056 goto error_open;
4057 }
4058 out->format = config->format;
4059 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4060 out->config = pcm_config_afe_proxy_playback;
4061 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004062 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304063 unsigned int channels = 0;
4064 /*Update config params to default if not set by the caller*/
4065 if (config->sample_rate == 0)
4066 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4067 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4068 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4069 if (config->format == AUDIO_FORMAT_DEFAULT)
4070 config->format = AUDIO_FORMAT_PCM_16_BIT;
4071
4072 channels = audio_channel_count_from_out_mask(out->channel_mask);
4073
Ashish Jain83a6cc22016-06-28 14:34:17 +05304074 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4075 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004076 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4077 out->flags);
4078 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304079 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4080 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4081 out->config = pcm_config_low_latency;
4082 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4083 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4084 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304085 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4086 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4087 if (out->config.period_size <= 0) {
4088 ALOGE("Invalid configuration period size is not valid");
4089 ret = -EINVAL;
4090 goto error_open;
4091 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304092 } else {
4093 /* primary path is the default path selected if no other outputs are available/suitable */
4094 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4095 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4096 }
4097 out->hal_ip_format = format = out->format;
4098 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4099 out->hal_op_format = pcm_format_to_hal(out->config.format);
4100 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4101 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004102 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304103 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304104 if (out->hal_ip_format != out->hal_op_format) {
4105 uint32_t buffer_size = out->config.period_size *
4106 format_to_bitwidth_table[out->hal_op_format] *
4107 out->config.channels;
4108 out->convert_buffer = calloc(1, buffer_size);
4109 if (out->convert_buffer == NULL){
4110 ALOGE("Allocation failed for convert buffer for size %d",
4111 out->compr_config.fragment_size);
4112 ret = -ENOMEM;
4113 goto error_open;
4114 }
4115 ALOGD("Convert buffer allocated of size %d", buffer_size);
4116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117 }
4118
Ashish Jain83a6cc22016-06-28 14:34:17 +05304119 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4120 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4121
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004122 /* TODO remove this hardcoding and check why width is zero*/
4123 if (out->bit_width == 0)
4124 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304125 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004126 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004127 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304128 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304129 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004130 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4131 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4132 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004133 if(adev->primary_output == NULL)
4134 adev->primary_output = out;
4135 else {
4136 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004137 ret = -EEXIST;
4138 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004139 }
4140 }
4141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 /* Check if this usecase is already existing */
4143 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004144 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4145 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004148 ret = -EEXIST;
4149 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 }
4151 pthread_mutex_unlock(&adev->lock);
4152
4153 out->stream.common.get_sample_rate = out_get_sample_rate;
4154 out->stream.common.set_sample_rate = out_set_sample_rate;
4155 out->stream.common.get_buffer_size = out_get_buffer_size;
4156 out->stream.common.get_channels = out_get_channels;
4157 out->stream.common.get_format = out_get_format;
4158 out->stream.common.set_format = out_set_format;
4159 out->stream.common.standby = out_standby;
4160 out->stream.common.dump = out_dump;
4161 out->stream.common.set_parameters = out_set_parameters;
4162 out->stream.common.get_parameters = out_get_parameters;
4163 out->stream.common.add_audio_effect = out_add_audio_effect;
4164 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4165 out->stream.get_latency = out_get_latency;
4166 out->stream.set_volume = out_set_volume;
4167 out->stream.write = out_write;
4168 out->stream.get_render_position = out_get_render_position;
4169 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004170 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004172 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004174 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004175 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176
4177 config->format = out->stream.common.get_format(&out->stream.common);
4178 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4179 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4180
4181 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304182 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004183 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004184
4185 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4186 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4187 popcount(out->channel_mask), out->playback_started);
4188
Eric Laurent994a6932013-07-17 11:51:42 -07004189 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004191
4192error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304193 if (out->convert_buffer)
4194 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004195 free(out);
4196 *stream_out = NULL;
4197 ALOGD("%s: exit: ret %d", __func__, ret);
4198 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199}
4200
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304201void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 struct audio_stream_out *stream)
4203{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004204 struct stream_out *out = (struct stream_out *)stream;
4205 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004206 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004207
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304208 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4209
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004210 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304211 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004212 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304213 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004214 if(ret != 0)
4215 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4216 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004217 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004218 out_standby(&stream->common);
4219
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004220 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004221 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004222 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004223 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004224 if (out->compr_config.codec != NULL)
4225 free(out->compr_config.codec);
4226 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004227
Ashish Jain83a6cc22016-06-28 14:34:17 +05304228 if (out->convert_buffer != NULL) {
4229 free(out->convert_buffer);
4230 out->convert_buffer = NULL;
4231 }
4232
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004233 if (adev->voice_tx_output == out)
4234 adev->voice_tx_output = NULL;
4235
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004236 pthread_cond_destroy(&out->cond);
4237 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004239 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240}
4241
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004242static void close_compress_sessions(struct audio_device *adev)
4243{
Mingming Yin7b762e72015-03-04 13:47:32 -08004244 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304245 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004246 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004247 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304248
4249 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004250 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304251 if (is_offload_usecase(usecase->id)) {
4252 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004253 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4254 out = usecase->stream.out;
4255 pthread_mutex_unlock(&adev->lock);
4256 out_standby(&out->stream.common);
4257 pthread_mutex_lock(&adev->lock);
4258 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304259 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004260 }
4261 pthread_mutex_unlock(&adev->lock);
4262}
4263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4265{
4266 struct audio_device *adev = (struct audio_device *)dev;
4267 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004269 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004270 int ret;
4271 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004273 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304276 if (!parms)
4277 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004278 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4279 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304280 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304281 if (strstr(snd_card_status, "OFFLINE")) {
4282 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304283 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004284 //close compress sessions on OFFLINE status
4285 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304286 } else if (strstr(snd_card_status, "ONLINE")) {
4287 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304288 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004289 //send dts hpx license if enabled
4290 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304291 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304292 }
4293
4294 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004295 status = voice_set_parameters(adev, parms);
4296 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004297 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004299 status = platform_set_parameters(adev->platform, parms);
4300 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004301 goto done;
4302
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004303 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4304 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004305 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4307 adev->bluetooth_nrec = true;
4308 else
4309 adev->bluetooth_nrec = false;
4310 }
4311
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004312 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4313 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4315 adev->screen_off = false;
4316 else
4317 adev->screen_off = true;
4318 }
4319
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004320 ret = str_parms_get_int(parms, "rotation", &val);
4321 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004322 bool reverse_speakers = false;
4323 switch(val) {
4324 // FIXME: note that the code below assumes that the speakers are in the correct placement
4325 // relative to the user when the device is rotated 90deg from its default rotation. This
4326 // assumption is device-specific, not platform-specific like this code.
4327 case 270:
4328 reverse_speakers = true;
4329 break;
4330 case 0:
4331 case 90:
4332 case 180:
4333 break;
4334 default:
4335 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004336 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004337 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004338 if (status == 0) {
4339 if (adev->speaker_lr_swap != reverse_speakers) {
4340 adev->speaker_lr_swap = reverse_speakers;
4341 // only update the selected device if there is active pcm playback
4342 struct audio_usecase *usecase;
4343 struct listnode *node;
4344 list_for_each(node, &adev->usecase_list) {
4345 usecase = node_to_item(node, struct audio_usecase, list);
4346 if (usecase->type == PCM_PLAYBACK) {
4347 select_devices(adev, usecase->id);
4348 break;
4349 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004350 }
4351 }
4352 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004353 }
4354
Mingming Yin514a8bc2014-07-29 15:22:21 -07004355 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4356 if (ret >= 0) {
4357 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4358 adev->bt_wb_speech_enabled = true;
4359 else
4360 adev->bt_wb_speech_enabled = false;
4361 }
4362
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004363 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4364 if (ret >= 0) {
4365 val = atoi(value);
4366 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004367 ALOGV("cache new ext disp type and edid");
4368 ret = platform_get_ext_disp_type(adev->platform);
4369 if (ret < 0) {
4370 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004371 status = ret;
4372 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004373 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004374 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004375 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004376 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004377 /*
4378 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4379 * Per AudioPolicyManager, USB device is higher priority than WFD.
4380 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4381 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4382 * starting voice call on USB
4383 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004384 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4385 if (ret >= 0) {
4386 audio_extn_usb_add_device(val, atoi(value));
4387 }
vivek mehta344576a2016-04-12 18:56:03 -07004388 ALOGV("detected USB connect .. disable proxy");
4389 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004390 }
4391 }
4392
4393 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4394 if (ret >= 0) {
4395 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004396 /*
4397 * The HDMI / Displayport disconnect handling has been moved to
4398 * audio extension to ensure that its parameters are not
4399 * invalidated prior to updating sysfs of the disconnect event
4400 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4401 */
4402 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004403 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004404 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4405 if (ret >= 0) {
4406 audio_extn_usb_remove_device(val, atoi(value));
4407 }
vivek mehta344576a2016-04-12 18:56:03 -07004408 ALOGV("detected USB disconnect .. enable proxy");
4409 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004410 }
4411 }
4412
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304413 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4414 if (ret >= 0) {
4415 struct audio_usecase *usecase;
4416 struct listnode *node;
4417 list_for_each(node, &adev->usecase_list) {
4418 usecase = node_to_item(node, struct audio_usecase, list);
4419 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004420 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304421 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304422 lock_output_stream(usecase->stream.out);
4423 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304424 //force device switch to re configure encoder
4425 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304426 audio_extn_a2dp_set_handoff_mode(false);
4427 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304428 break;
4429 }
4430 }
4431 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304432 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004433done:
4434 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004435 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304436error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004437 ALOGV("%s: exit with code(%d)", __func__, status);
4438 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439}
4440
4441static char* adev_get_parameters(const struct audio_hw_device *dev,
4442 const char *keys)
4443{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004444 struct audio_device *adev = (struct audio_device *)dev;
4445 struct str_parms *reply = str_parms_create();
4446 struct str_parms *query = str_parms_create_str(keys);
4447 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304448 char value[256] = {0};
4449 int ret = 0;
4450
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004451 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004452 if (reply) {
4453 str_parms_destroy(reply);
4454 }
4455 if (query) {
4456 str_parms_destroy(query);
4457 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004458 ALOGE("adev_get_parameters: failed to create query or reply");
4459 return NULL;
4460 }
4461
Naresh Tannirud7205b62014-06-20 02:54:48 +05304462 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4463 sizeof(value));
4464 if (ret >=0) {
4465 int val = 1;
4466 pthread_mutex_lock(&adev->snd_card_status.lock);
4467 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4468 val = 0;
4469 pthread_mutex_unlock(&adev->snd_card_status.lock);
4470 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4471 goto exit;
4472 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004473
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004474 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004475 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004476 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004477 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304478 pthread_mutex_unlock(&adev->lock);
4479
Naresh Tannirud7205b62014-06-20 02:54:48 +05304480exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004481 str = str_parms_to_str(reply);
4482 str_parms_destroy(query);
4483 str_parms_destroy(reply);
4484
4485 ALOGV("%s: exit: returns - %s", __func__, str);
4486 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487}
4488
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004489static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490{
4491 return 0;
4492}
4493
4494static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4495{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004496 int ret;
4497 struct audio_device *adev = (struct audio_device *)dev;
4498 pthread_mutex_lock(&adev->lock);
4499 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004500 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004501 pthread_mutex_unlock(&adev->lock);
4502 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503}
4504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004505static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4506 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507{
4508 return -ENOSYS;
4509}
4510
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004511static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4512 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513{
4514 return -ENOSYS;
4515}
4516
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004517static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4518 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519{
4520 return -ENOSYS;
4521}
4522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004523static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4524 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525{
4526 return -ENOSYS;
4527}
4528
4529static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4530{
4531 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004533 pthread_mutex_lock(&adev->lock);
4534 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004535 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004536 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004537 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004538 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004539 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004540 adev->current_call_output = NULL;
4541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 }
4543 pthread_mutex_unlock(&adev->lock);
4544 return 0;
4545}
4546
4547static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4548{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004549 int ret;
4550
4551 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004552 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004553 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4554 pthread_mutex_unlock(&adev->lock);
4555
4556 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557}
4558
4559static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4560{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004561 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 return 0;
4563}
4564
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004565static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 const struct audio_config *config)
4567{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004568 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004570 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4571 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572}
4573
4574static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004575 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 audio_devices_t devices,
4577 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004578 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304579 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004580 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004581 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582{
4583 struct audio_device *adev = (struct audio_device *)dev;
4584 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004585 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004586 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004587 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304588 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304591 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4592 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304594 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595
4596 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004597
4598 if (!in) {
4599 ALOGE("failed to allocate input stream");
4600 return -ENOMEM;
4601 }
4602
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304603 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304604 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4605 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004606 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004607 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609 in->stream.common.get_sample_rate = in_get_sample_rate;
4610 in->stream.common.set_sample_rate = in_set_sample_rate;
4611 in->stream.common.get_buffer_size = in_get_buffer_size;
4612 in->stream.common.get_channels = in_get_channels;
4613 in->stream.common.get_format = in_get_format;
4614 in->stream.common.set_format = in_set_format;
4615 in->stream.common.standby = in_standby;
4616 in->stream.common.dump = in_dump;
4617 in->stream.common.set_parameters = in_set_parameters;
4618 in->stream.common.get_parameters = in_get_parameters;
4619 in->stream.common.add_audio_effect = in_add_audio_effect;
4620 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4621 in->stream.set_gain = in_set_gain;
4622 in->stream.read = in_read;
4623 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4624
4625 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004626 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 in->standby = 1;
4629 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004630 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004631 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004633 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004634 if (in->realtime) {
4635 in->config = pcm_config_audio_capture_rt;
4636 in->sample_rate = in->config.rate;
4637 in->af_period_multiplier = af_period_multiplier;
4638 } else {
4639 in->config = pcm_config_audio_capture;
4640 in->config.rate = config->sample_rate;
4641 in->sample_rate = config->sample_rate;
4642 in->af_period_multiplier = 1;
4643 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304644 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304646 /* restrict 24 bit capture for unprocessed source only
4647 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4648 */
4649 if (config->format == AUDIO_FORMAT_DEFAULT) {
4650 config->format = AUDIO_FORMAT_PCM_16_BIT;
4651 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4652 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4653 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4654 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4655 bool ret_error = false;
4656 in->bit_width = 24;
4657 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4658 from HAL is 24_packed and 8_24
4659 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4660 24_packed return error indicating supported format is 24_packed
4661 *> In case of any other source requesting 24 bit or float return error
4662 indicating format supported is 16 bit only.
4663
4664 on error flinger will retry with supported format passed
4665 */
4666 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4667 (source != AUDIO_SOURCE_CAMCORDER)) {
4668 config->format = AUDIO_FORMAT_PCM_16_BIT;
4669 if (config->sample_rate > 48000)
4670 config->sample_rate = 48000;
4671 ret_error = true;
4672 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4673 in->config.format = PCM_FORMAT_S24_3LE;
4674 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4675 in->config.format = PCM_FORMAT_S24_LE;
4676 } else {
4677 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4678 ret_error = true;
4679 }
4680
4681 if (ret_error) {
4682 ret = -EINVAL;
4683 goto err_open;
4684 }
4685 }
4686
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304687 in->usecase = USECASE_AUDIO_RECORD;
4688 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4689 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4690 is_low_latency = true;
4691#if LOW_LATENCY_CAPTURE_USE_CASE
4692 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4693#endif
4694 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4695 }
4696
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304697 pthread_mutex_lock(&adev->lock);
4698 if (in->usecase == USECASE_AUDIO_RECORD) {
4699 if (!(adev->pcm_record_uc_state) &&
4700 ((flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0)) {
4701 ALOGV("%s: pcm record usecase", __func__);
4702 adev->pcm_record_uc_state = 1;
4703 } else {
4704 /*
4705 * Assign default compress record use case, actual use case
4706 * assignment will happen later.
4707 */
4708 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
4709 ALOGV("%s: compress record usecase", __func__);
4710 }
4711 }
4712 pthread_mutex_unlock(&adev->lock);
4713
4714 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304715 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4716 (adev->mode != AUDIO_MODE_IN_CALL)) {
4717 ret = -EINVAL;
4718 goto err_open;
4719 }
4720
4721 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4722 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004723 if (config->sample_rate == 0)
4724 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4725 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4726 config->sample_rate != 8000) {
4727 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4728 ret = -EINVAL;
4729 goto err_open;
4730 }
4731 if (config->format == AUDIO_FORMAT_DEFAULT)
4732 config->format = AUDIO_FORMAT_PCM_16_BIT;
4733 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4734 config->format = AUDIO_FORMAT_PCM_16_BIT;
4735 ret = -EINVAL;
4736 goto err_open;
4737 }
4738
4739 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4740 in->config = pcm_config_afe_proxy_record;
4741 in->config.channels = channel_count;
4742 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304743 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304744 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4745 in, config, &channel_mask_updated)) {
4746 if (channel_mask_updated == true) {
4747 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4748 __func__, config->channel_mask);
4749 ret = -EINVAL;
4750 goto err_open;
4751 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304752 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004753 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004754 audio_extn_compr_cap_format_supported(config->format) &&
4755 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004756 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304757 } else if (audio_extn_cin_applicable_stream(in)) {
4758 ret = audio_extn_cin_configure_input_stream(in);
4759 if (ret)
4760 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004761 } else {
4762 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004763 if (!in->realtime) {
4764 in->format = config->format;
4765 frame_size = audio_stream_in_frame_size(&in->stream);
4766 buffer_size = get_input_buffer_size(config->sample_rate,
4767 config->format,
4768 channel_count,
4769 is_low_latency);
4770 in->config.period_size = buffer_size / frame_size;
4771 }
4772
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004773 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4774 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4775 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004776 (in->config.rate == 8000 || in->config.rate == 16000 ||
4777 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004778 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4779 voice_extn_compress_voip_open_input_stream(in);
4780 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004782
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304783 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4784 &adev->streams_input_cfg_list,
4785 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304786 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304787
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004788 /* This stream could be for sound trigger lab,
4789 get sound trigger pcm if present */
4790 audio_extn_sound_trigger_check_and_get_session(in);
4791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004793 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004794 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795
4796err_open:
4797 free(in);
4798 *stream_in = NULL;
4799 return ret;
4800}
4801
4802static void adev_close_input_stream(struct audio_hw_device *dev,
4803 struct audio_stream_in *stream)
4804{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004805 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004806 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004807 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304808
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304809 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004810
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304811 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004812 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304813
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004814 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304815 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004816 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304817 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004818 if (ret != 0)
4819 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4820 __func__, ret);
4821 } else
4822 in_standby(&stream->common);
4823
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004824 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004825 audio_extn_ssr_deinit();
4826 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304828 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004829 audio_extn_compr_cap_format_supported(in->config.format))
4830 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304831
4832 if (in->usecase == USECASE_AUDIO_RECORD) {
4833 pthread_mutex_lock(&adev->lock);
4834 adev->pcm_record_uc_state = 0;
4835 pthread_mutex_unlock(&adev->lock);
4836 }
4837
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304838 if (audio_extn_cin_attached_usecase(in->usecase))
4839 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004840
Mingming Yinfd7607b2016-01-22 12:48:44 -08004841 if (in->is_st_session) {
4842 ALOGV("%s: sound trigger pcm stop lab", __func__);
4843 audio_extn_sound_trigger_stop_lab(in);
4844 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004845 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846 return;
4847}
4848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004849static int adev_dump(const audio_hw_device_t *device __unused,
4850 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851{
4852 return 0;
4853}
4854
4855static int adev_close(hw_device_t *device)
4856{
4857 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004858
4859 if (!adev)
4860 return 0;
4861
4862 pthread_mutex_lock(&adev_init_lock);
4863
4864 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004865 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004866 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304867 audio_extn_utils_release_streams_cfg_lists(
4868 &adev->streams_output_cfg_list,
4869 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304870 if (audio_extn_qaf_is_enabled())
4871 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004872 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004873 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004874 free(adev->snd_dev_ref_cnt);
4875 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004876 if (adev->adm_deinit)
4877 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304878 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004879 free(device);
4880 adev = NULL;
4881 }
4882 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884 return 0;
4885}
4886
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004887/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4888 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4889 * just that it _might_ work.
4890 */
4891static int period_size_is_plausible_for_low_latency(int period_size)
4892{
4893 switch (period_size) {
4894 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004895 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004896 case 240:
4897 case 320:
4898 case 480:
4899 return 1;
4900 default:
4901 return 0;
4902 }
4903}
4904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004905static int adev_open(const hw_module_t *module, const char *name,
4906 hw_device_t **device)
4907{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304908 int ret;
4909
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004910 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4912
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004913 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004914 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004915 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004916 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004917 ALOGD("%s: returning existing instance of adev", __func__);
4918 ALOGD("%s: exit", __func__);
4919 pthread_mutex_unlock(&adev_init_lock);
4920 return 0;
4921 }
4922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004923 adev = calloc(1, sizeof(struct audio_device));
4924
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004925 if (!adev) {
4926 pthread_mutex_unlock(&adev_init_lock);
4927 return -ENOMEM;
4928 }
4929
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004930 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4933 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4934 adev->device.common.module = (struct hw_module_t *)module;
4935 adev->device.common.close = adev_close;
4936
4937 adev->device.init_check = adev_init_check;
4938 adev->device.set_voice_volume = adev_set_voice_volume;
4939 adev->device.set_master_volume = adev_set_master_volume;
4940 adev->device.get_master_volume = adev_get_master_volume;
4941 adev->device.set_master_mute = adev_set_master_mute;
4942 adev->device.get_master_mute = adev_get_master_mute;
4943 adev->device.set_mode = adev_set_mode;
4944 adev->device.set_mic_mute = adev_set_mic_mute;
4945 adev->device.get_mic_mute = adev_get_mic_mute;
4946 adev->device.set_parameters = adev_set_parameters;
4947 adev->device.get_parameters = adev_get_parameters;
4948 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4949 adev->device.open_output_stream = adev_open_output_stream;
4950 adev->device.close_output_stream = adev_close_output_stream;
4951 adev->device.open_input_stream = adev_open_input_stream;
4952 adev->device.close_input_stream = adev_close_input_stream;
4953 adev->device.dump = adev_dump;
4954
4955 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004957 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004958 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004960 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004961 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004962 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004963 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004964 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004965 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004966 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004967 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004968 adev->offload_usecases_state = 0;
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304969 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304970 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304971 adev->perf_lock_opts[0] = 0x101;
4972 adev->perf_lock_opts[1] = 0x20E;
4973 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304974
4975 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4976 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004978 adev->platform = platform_init(adev);
4979 if (!adev->platform) {
4980 free(adev->snd_dev_ref_cnt);
4981 free(adev);
4982 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4983 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004984 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304985 pthread_mutex_destroy(&adev->lock);
4986 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004987 return -EINVAL;
4988 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004989
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304990 if (audio_extn_qaf_is_enabled()) {
4991 ret = audio_extn_qaf_init(adev);
4992 if (ret < 0) {
4993 free(adev);
4994 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4995 *device = NULL;
4996 pthread_mutex_unlock(&adev_init_lock);
4997 pthread_mutex_destroy(&adev->lock);
4998 return ret;
4999 }
5000
5001 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5002 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5003 }
5004
Naresh Tanniru4c630392014-05-12 01:05:52 +05305005 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5006
Eric Laurentc4aef752013-09-12 17:45:53 -07005007 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5008 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5009 if (adev->visualizer_lib == NULL) {
5010 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5011 } else {
5012 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5013 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005014 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005015 "visualizer_hal_start_output");
5016 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005017 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005018 "visualizer_hal_stop_output");
5019 }
5020 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305021 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005022 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005023 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005024 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005025
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005026 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5027 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5028 if (adev->offload_effects_lib == NULL) {
5029 ALOGE("%s: DLOPEN failed for %s", __func__,
5030 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5031 } else {
5032 ALOGV("%s: DLOPEN successful for %s", __func__,
5033 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5034 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305035 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005036 "offload_effects_bundle_hal_start_output");
5037 adev->offload_effects_stop_output =
5038 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5039 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005040 adev->offload_effects_set_hpx_state =
5041 (int (*)(bool))dlsym(adev->offload_effects_lib,
5042 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305043 adev->offload_effects_get_parameters =
5044 (void (*)(struct str_parms *, struct str_parms *))
5045 dlsym(adev->offload_effects_lib,
5046 "offload_effects_bundle_get_parameters");
5047 adev->offload_effects_set_parameters =
5048 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5049 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005050 }
5051 }
5052
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005053 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5054 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5055 if (adev->adm_lib == NULL) {
5056 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5057 } else {
5058 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5059 adev->adm_init = (adm_init_t)
5060 dlsym(adev->adm_lib, "adm_init");
5061 adev->adm_deinit = (adm_deinit_t)
5062 dlsym(adev->adm_lib, "adm_deinit");
5063 adev->adm_register_input_stream = (adm_register_input_stream_t)
5064 dlsym(adev->adm_lib, "adm_register_input_stream");
5065 adev->adm_register_output_stream = (adm_register_output_stream_t)
5066 dlsym(adev->adm_lib, "adm_register_output_stream");
5067 adev->adm_deregister_stream = (adm_deregister_stream_t)
5068 dlsym(adev->adm_lib, "adm_deregister_stream");
5069 adev->adm_request_focus = (adm_request_focus_t)
5070 dlsym(adev->adm_lib, "adm_request_focus");
5071 adev->adm_abandon_focus = (adm_abandon_focus_t)
5072 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005073 adev->adm_set_config = (adm_set_config_t)
5074 dlsym(adev->adm_lib, "adm_set_config");
5075 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5076 dlsym(adev->adm_lib, "adm_request_focus_v2");
5077 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5078 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5079 adev->adm_on_routing_change = (adm_on_routing_change_t)
5080 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005081 }
5082 }
5083
Mingming Yin514a8bc2014-07-29 15:22:21 -07005084 adev->bt_wb_speech_enabled = false;
5085
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005086 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087 *device = &adev->device.common;
5088
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305089 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5090 &adev->streams_output_cfg_list,
5091 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005092
Kiran Kandi910e1862013-10-29 13:29:42 -07005093 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005094
5095 char value[PROPERTY_VALUE_MAX];
5096 int trial;
5097 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5098 trial = atoi(value);
5099 if (period_size_is_plausible_for_low_latency(trial)) {
5100 pcm_config_low_latency.period_size = trial;
5101 pcm_config_low_latency.start_threshold = trial / 4;
5102 pcm_config_low_latency.avail_min = trial / 4;
5103 configured_low_latency_capture_period_size = trial;
5104 }
5105 }
5106 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5107 trial = atoi(value);
5108 if (period_size_is_plausible_for_low_latency(trial)) {
5109 configured_low_latency_capture_period_size = trial;
5110 }
5111 }
5112
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005113 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5114 af_period_multiplier = atoi(value);
5115 if (af_period_multiplier < 0)
5116 af_period_multiplier = 2;
5117 else if (af_period_multiplier > 4)
5118 af_period_multiplier = 4;
5119
5120 ALOGV("new period_multiplier = %d", af_period_multiplier);
5121 }
5122
vivek mehta446c3962015-09-14 10:57:35 -07005123 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005124 pthread_mutex_unlock(&adev_init_lock);
5125
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005126 if (adev->adm_init)
5127 adev->adm_data = adev->adm_init();
5128
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305129 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305130 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005131 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005132 return 0;
5133}
5134
5135static struct hw_module_methods_t hal_module_methods = {
5136 .open = adev_open,
5137};
5138
5139struct audio_module HAL_MODULE_INFO_SYM = {
5140 .common = {
5141 .tag = HARDWARE_MODULE_TAG,
5142 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5143 .hal_api_version = HARDWARE_HAL_API_VERSION,
5144 .id = AUDIO_HARDWARE_MODULE_ID,
5145 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005146 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147 .methods = &hal_module_methods,
5148 },
5149};