blob: d275e3ddda63644add4c082f838917cd6716eabf [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;
1092
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301093 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1094 snd_device);
1095 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001096 /*
1097 * This function is to make sure that all the active capture usecases
1098 * are always routed to the same input sound device.
1099 * For example, if audio-record and voice-call usecases are currently
1100 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1101 * is received for voice call then we have to make sure that audio-record
1102 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1103 * because of the limitation that two devices cannot be enabled
1104 * at the same time if they share the same backend.
1105 */
1106 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1107 switch_device[i] = false;
1108
1109 list_for_each(node, &adev->usecase_list) {
1110 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001111 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001112 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301113 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -07001114 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301115 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001116 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001117 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001118 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1119 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001120 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001121 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001122 switch_device[usecase->id] = true;
1123 num_uc_to_switch++;
1124 }
1125 }
1126
1127 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001128 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001129
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301130 /* Make sure the previous devices to be disabled first and then enable the
1131 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001132 list_for_each(node, &adev->usecase_list) {
1133 usecase = node_to_item(node, struct audio_usecase, list);
1134 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001135 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001136 }
1137 }
1138
1139 list_for_each(node, &adev->usecase_list) {
1140 usecase = node_to_item(node, struct audio_usecase, list);
1141 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001142 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001143 }
1144 }
1145
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001146 /* Re-route all the usecases on the shared backend other than the
1147 specified usecase to new snd devices */
1148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
1150 /* Update the in_snd_device only before enabling the audio route */
1151 if (switch_device[usecase->id] ) {
1152 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001153 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301154 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001155 }
1156 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001157 }
1158}
1159
Mingming Yin3a941d42016-02-17 18:08:05 -08001160static void reset_hdmi_sink_caps(struct stream_out *out) {
1161 int i = 0;
1162
1163 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1164 out->supported_channel_masks[i] = 0;
1165 }
1166 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1167 out->supported_formats[i] = 0;
1168 }
1169 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1170 out->supported_sample_rates[i] = 0;
1171 }
1172}
1173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001175static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176{
Mingming Yin3a941d42016-02-17 18:08:05 -08001177 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001178 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179
Mingming Yin3a941d42016-02-17 18:08:05 -08001180 reset_hdmi_sink_caps(out);
1181
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001182 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001183 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001184 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001185 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001186 }
1187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001190 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001191 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001192 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1193 case 6:
1194 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1195 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1196 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1197 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1198 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1199 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200 break;
1201 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001202 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001203 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 break;
1205 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001206
1207 // check channel format caps
1208 i = 0;
1209 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1210 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1211 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1212 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1213 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1214 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1215 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1216 }
1217
1218 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1219 ALOGV(":%s HDMI supports DTS format", __func__);
1220 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1221 }
1222
1223 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1224 ALOGV(":%s HDMI supports DTS HD format", __func__);
1225 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1226 }
1227
1228
1229 // check sample rate caps
1230 i = 0;
1231 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1232 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1233 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1234 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1235 }
1236 }
1237
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001238 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239}
1240
Alexy Josephb1379942016-01-29 15:49:38 -08001241audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001242 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001243{
1244 struct audio_usecase *usecase;
1245 struct listnode *node;
1246
1247 list_for_each(node, &adev->usecase_list) {
1248 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001249 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001250 ALOGV("%s: usecase id %d", __func__, usecase->id);
1251 return usecase->id;
1252 }
1253 }
1254 return USECASE_INVALID;
1255}
1256
Alexy Josephb1379942016-01-29 15:49:38 -08001257struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001258 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259{
1260 struct audio_usecase *usecase;
1261 struct listnode *node;
1262
1263 list_for_each(node, &adev->usecase_list) {
1264 usecase = node_to_item(node, struct audio_usecase, list);
1265 if (usecase->id == uc_id)
1266 return usecase;
1267 }
1268 return NULL;
1269}
1270
Dhananjay Kumard4833242016-10-06 22:09:12 +05301271struct stream_in *get_next_active_input(const struct audio_device *adev)
1272{
1273 struct audio_usecase *usecase;
1274 struct listnode *node;
1275
1276 list_for_each_reverse(node, &adev->usecase_list) {
1277 usecase = node_to_item(node, struct audio_usecase, list);
1278 if (usecase->type == PCM_CAPTURE)
1279 return usecase->stream.in;
1280 }
1281 return NULL;
1282}
1283
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301284/*
1285 * is a true native playback active
1286 */
1287bool audio_is_true_native_stream_active(struct audio_device *adev)
1288{
1289 bool active = false;
1290 int i = 0;
1291 struct listnode *node;
1292
1293 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1294 ALOGV("%s:napb: not in true mode or non hdphones device",
1295 __func__);
1296 active = false;
1297 goto exit;
1298 }
1299
1300 list_for_each(node, &adev->usecase_list) {
1301 struct audio_usecase *uc;
1302 uc = node_to_item(node, struct audio_usecase, list);
1303 struct stream_out *curr_out =
1304 (struct stream_out*) uc->stream.out;
1305
1306 if (curr_out && PCM_PLAYBACK == uc->type) {
1307 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1308 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1309 uc->id, curr_out->sample_rate,
1310 curr_out->bit_width,
1311 platform_get_snd_device_name(uc->out_snd_device));
1312
1313 if (is_offload_usecase(uc->id) &&
1314 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1315 active = true;
1316 ALOGD("%s:napb:native stream detected", __func__);
1317 }
1318 }
1319 }
1320exit:
1321 return active;
1322}
1323
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301324/*
1325 * if native DSD playback active
1326 */
1327bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1328{
1329 bool active = false;
1330 struct listnode *node = NULL;
1331 struct audio_usecase *uc = NULL;
1332 struct stream_out *curr_out = NULL;
1333
1334 list_for_each(node, &adev->usecase_list) {
1335 uc = node_to_item(node, struct audio_usecase, list);
1336 curr_out = (struct stream_out*) uc->stream.out;
1337
1338 if (curr_out && PCM_PLAYBACK == uc->type &&
1339 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1340 active = true;
1341 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301342 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301343 }
1344 }
1345 return active;
1346}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301347
1348static bool force_device_switch(struct audio_usecase *usecase)
1349{
1350 bool ret = false;
1351 bool is_it_true_mode = false;
1352
1353 if (is_offload_usecase(usecase->id) &&
1354 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001355 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1356 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1357 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301358 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1359 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1360 (!is_it_true_mode && adev->native_playback_enabled)){
1361 ret = true;
1362 ALOGD("napb: time to toggle native mode");
1363 }
1364 }
1365
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301366 // Force all a2dp output devices to reconfigure for proper AFE encode format
1367 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001368 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301369 audio_extn_a2dp_is_force_device_switch()) {
1370 ALOGD("Force a2dp device switch to update new encoder config");
1371 ret = true;
1372 }
1373
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301374 return ret;
1375}
1376
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001377int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001379 snd_device_t out_snd_device = SND_DEVICE_NONE;
1380 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001381 struct audio_usecase *usecase = NULL;
1382 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001383 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001384 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001385 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001386 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001387
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301388 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1389
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001390 usecase = get_usecase_from_list(adev, uc_id);
1391 if (usecase == NULL) {
1392 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1393 return -EINVAL;
1394 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001396 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001397 (usecase->type == VOIP_CALL) ||
1398 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301399 if(usecase->stream.out == NULL) {
1400 ALOGE("%s: stream.out is NULL", __func__);
1401 return -EINVAL;
1402 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001403 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001404 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001405 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001406 usecase->devices = usecase->stream.out->devices;
1407 } else {
1408 /*
1409 * If the voice call is active, use the sound devices of voice call usecase
1410 * so that it would not result any device switch. All the usecases will
1411 * be switched to new device when select_devices() is called for voice call
1412 * usecase. This is to avoid switching devices for voice call when
1413 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001414 * choose voice call device only if the use case device is
1415 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001417 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001418 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001419 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001420 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1421 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301422 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1423 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001424 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425 in_snd_device = vc_usecase->in_snd_device;
1426 out_snd_device = vc_usecase->out_snd_device;
1427 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001428 } else if (voice_extn_compress_voip_is_active(adev)) {
1429 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001430 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001431 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1432 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001433 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001434 in_snd_device = voip_usecase->in_snd_device;
1435 out_snd_device = voip_usecase->out_snd_device;
1436 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001437 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001438 hfp_ucid = audio_extn_hfp_get_usecase();
1439 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001440 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001441 in_snd_device = hfp_usecase->in_snd_device;
1442 out_snd_device = hfp_usecase->out_snd_device;
1443 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 }
1445 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301446 if (usecase->stream.out == NULL) {
1447 ALOGE("%s: stream.out is NULL", __func__);
1448 return -EINVAL;
1449 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001450 usecase->devices = usecase->stream.out->devices;
1451 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001452 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001453 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001454 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001455 if (usecase->stream.out == adev->primary_output &&
1456 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001457 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001458 select_devices(adev, adev->active_input->usecase);
1459 }
1460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301462 if (usecase->stream.in == NULL) {
1463 ALOGE("%s: stream.in is NULL", __func__);
1464 return -EINVAL;
1465 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 usecase->devices = usecase->stream.in->device;
1467 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001468 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001469 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001470 if (adev->active_input &&
1471 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301472 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1473 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1474 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001475 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001476 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001477 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1478 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001479 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001480 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001481 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 }
1483 }
1484
1485 if (out_snd_device == usecase->out_snd_device &&
1486 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301487
1488 if (!force_device_switch(usecase))
1489 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 }
1491
sangwoobc677242013-08-08 16:53:43 +09001492 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001493 out_snd_device, platform_get_snd_device_name(out_snd_device),
1494 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 /*
1497 * Limitation: While in call, to do a device switch we need to disable
1498 * and enable both RX and TX devices though one of them is same as current
1499 * device.
1500 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001501 if ((usecase->type == VOICE_CALL) &&
1502 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1503 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001504 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001505 }
1506
1507 if (((usecase->type == VOICE_CALL) ||
1508 (usecase->type == VOIP_CALL)) &&
1509 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1510 /* Disable sidetone only if voice/voip call already exists */
1511 if (voice_is_call_state_active(adev) ||
1512 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001513 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001514
1515 /* Disable aanc only if voice call exists */
1516 if (voice_is_call_state_active(adev))
1517 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001518 }
1519
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 /* Disable current sound devices */
1521 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001522 disable_audio_route(adev, usecase);
1523 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 }
1525
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001527 disable_audio_route(adev, usecase);
1528 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 }
1530
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001531 /* Applicable only on the targets that has external modem.
1532 * New device information should be sent to modem before enabling
1533 * the devices to reduce in-call device switch time.
1534 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001535 if ((usecase->type == VOICE_CALL) &&
1536 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1537 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001538 status = platform_switch_voice_call_enable_device_config(adev->platform,
1539 out_snd_device,
1540 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001541 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001542
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 /* Enable new sound devices */
1544 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001545 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301546 if (platform_check_codec_asrc_support(adev->platform))
1547 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001548 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 }
1550
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001551 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301552 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001553 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001554 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555
Avinash Vaish71a8b972014-07-24 15:36:33 +05301556 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 status = platform_switch_voice_call_device_post(adev->platform,
1558 out_snd_device,
1559 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301560 enable_audio_route_for_voice_usecases(adev, usecase);
1561 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001562
sangwoo170731f2013-06-08 15:36:36 +09001563 usecase->in_snd_device = in_snd_device;
1564 usecase->out_snd_device = out_snd_device;
1565
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301566 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1567 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301568 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001569 /* Notify device change info to effect clients registered */
1570 audio_extn_gef_notify_device_config(
1571 usecase->stream.out->devices,
1572 usecase->stream.out->channel_mask,
1573 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301574 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001575 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001576
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001577 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001578 /* Enable aanc only if voice call exists */
1579 if (voice_is_call_state_active(adev))
1580 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1581
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001582 /* Enable sidetone only if other voice/voip call already exists */
1583 if (voice_is_call_state_active(adev) ||
1584 voice_extn_compress_voip_is_started(adev))
1585 voice_set_sidetone(adev, out_snd_device, true);
1586 }
1587
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001588 /* Applicable only on the targets that has external modem.
1589 * Enable device command should be sent to modem only after
1590 * enabling voice call mixer controls
1591 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001592 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001593 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1594 out_snd_device,
1595 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301596 ALOGD("%s: done",__func__);
1597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 return status;
1599}
1600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601static int stop_input_stream(struct stream_in *in)
1602{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301603 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 struct audio_usecase *uc_info;
1605 struct audio_device *adev = in->dev;
1606
Dhananjay Kumard4833242016-10-06 22:09:12 +05301607 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608
Eric Laurent994a6932013-07-17 11:51:42 -07001609 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001610 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611 uc_info = get_usecase_from_list(adev, in->usecase);
1612 if (uc_info == NULL) {
1613 ALOGE("%s: Could not find the usecase (%d) in the list",
1614 __func__, in->usecase);
1615 return -EINVAL;
1616 }
1617
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001618 /* Close in-call recording streams */
1619 voice_check_and_stop_incall_rec_usecase(adev, in);
1620
Eric Laurent150dbfe2013-02-27 14:31:02 -08001621 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001622 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001623
1624 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001625 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001627 list_remove(&uc_info->list);
1628 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629
Eric Laurent994a6932013-07-17 11:51:42 -07001630 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631 return ret;
1632}
1633
1634int start_input_stream(struct stream_in *in)
1635{
1636 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001637 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 struct audio_usecase *uc_info;
1639 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301640 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Mingming Yin2664a5b2015-09-03 10:53:11 -07001642 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1643 if (get_usecase_from_list(adev, usecase) == NULL)
1644 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301645 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1646 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001647
Naresh Tanniru80659832014-06-04 18:17:56 +05301648
1649 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301650 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301651 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301652 goto error_config;
1653 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301654
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001655 /* Check if source matches incall recording usecase criteria */
1656 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1657 if (ret)
1658 goto error_config;
1659 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001660 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1661
1662 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1663 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1664 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001665 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001666 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001667
Eric Laurentb23d5282013-05-14 15:27:20 -07001668 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 if (in->pcm_device_id < 0) {
1670 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1671 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001672 ret = -EINVAL;
1673 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675
1676 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001678
1679 if (!uc_info) {
1680 ret = -ENOMEM;
1681 goto error_config;
1682 }
1683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 uc_info->id = in->usecase;
1685 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001686 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001687 uc_info->devices = in->device;
1688 uc_info->in_snd_device = SND_DEVICE_NONE;
1689 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001691 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301692 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1693 adev->perf_lock_opts,
1694 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001695 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301697 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1698 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001699
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301700 if (audio_extn_cin_attached_usecase(in->usecase)) {
1701 ret = audio_extn_cin_start_input_stream(in);
1702 if (ret)
1703 goto error_open;
1704 else
1705 goto done_open;
1706 }
1707
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001708 unsigned int flags = PCM_IN;
1709 unsigned int pcm_open_retry_count = 0;
1710
1711 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1712 flags |= PCM_MMAP | PCM_NOIRQ;
1713 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001714 } else if (in->realtime) {
1715 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001716 }
1717
1718 while (1) {
1719 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1720 flags, &in->config);
1721 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1722 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1723 if (in->pcm != NULL) {
1724 pcm_close(in->pcm);
1725 in->pcm = NULL;
1726 }
1727 if (pcm_open_retry_count-- == 0) {
1728 ret = -EIO;
1729 goto error_open;
1730 }
1731 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1732 continue;
1733 }
1734 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001736
1737 ALOGV("%s: pcm_prepare", __func__);
1738 ret = pcm_prepare(in->pcm);
1739 if (ret < 0) {
1740 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1741 pcm_close(in->pcm);
1742 in->pcm = NULL;
1743 goto error_open;
1744 }
1745
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001746 register_in_stream(in);
1747 if (in->realtime) {
1748 ret = pcm_start(in->pcm);
1749 if (ret < 0)
1750 goto error_open;
1751 }
1752
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301753done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301754 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001755 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001756
Eric Laurentc8400632013-02-14 19:04:54 -08001757 return ret;
1758
1759error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301760 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001762error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301763 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301764 /*
1765 * sleep 50ms to allow sufficient time for kernel
1766 * drivers to recover incases like SSR.
1767 */
1768 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001769 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001770
1771 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772}
1773
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001774void lock_input_stream(struct stream_in *in)
1775{
1776 pthread_mutex_lock(&in->pre_lock);
1777 pthread_mutex_lock(&in->lock);
1778 pthread_mutex_unlock(&in->pre_lock);
1779}
1780
1781void lock_output_stream(struct stream_out *out)
1782{
1783 pthread_mutex_lock(&out->pre_lock);
1784 pthread_mutex_lock(&out->lock);
1785 pthread_mutex_unlock(&out->pre_lock);
1786}
1787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788/* must be called with out->lock locked */
1789static int send_offload_cmd_l(struct stream_out* out, int command)
1790{
1791 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1792
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001793 if (!cmd) {
1794 ALOGE("failed to allocate mem for command 0x%x", command);
1795 return -ENOMEM;
1796 }
1797
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 ALOGVV("%s %d", __func__, command);
1799
1800 cmd->cmd = command;
1801 list_add_tail(&out->offload_cmd_list, &cmd->node);
1802 pthread_cond_signal(&out->offload_cond);
1803 return 0;
1804}
1805
1806/* must be called iwth out->lock locked */
1807static void stop_compressed_output_l(struct stream_out *out)
1808{
1809 out->offload_state = OFFLOAD_STATE_IDLE;
1810 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 if (out->compr != NULL) {
1813 compress_stop(out->compr);
1814 while (out->offload_thread_blocked) {
1815 pthread_cond_wait(&out->cond, &out->lock);
1816 }
1817 }
1818}
1819
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001820bool is_offload_usecase(audio_usecase_t uc_id)
1821{
1822 unsigned int i;
1823 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1824 if (uc_id == offload_usecases[i])
1825 return true;
1826 }
1827 return false;
1828}
1829
vivek mehta446c3962015-09-14 10:57:35 -07001830static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001831{
vivek mehta446c3962015-09-14 10:57:35 -07001832 audio_usecase_t ret_uc = USECASE_INVALID;
1833 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001834 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001835 if (!adev->multi_offload_enable) {
1836 if (is_direct_pcm)
1837 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1838 else
1839 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001840
vivek mehta446c3962015-09-14 10:57:35 -07001841 pthread_mutex_lock(&adev->lock);
1842 if (get_usecase_from_list(adev, ret_uc) != NULL)
1843 ret_uc = USECASE_INVALID;
1844 pthread_mutex_unlock(&adev->lock);
1845
1846 return ret_uc;
1847 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001848
1849 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001850 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1851 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1852 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1853 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001854 break;
1855 }
1856 }
vivek mehta446c3962015-09-14 10:57:35 -07001857
1858 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1859 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001860}
1861
1862static void free_offload_usecase(struct audio_device *adev,
1863 audio_usecase_t uc_id)
1864{
vivek mehta446c3962015-09-14 10:57:35 -07001865 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001866 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001867
1868 if (!adev->multi_offload_enable)
1869 return;
1870
1871 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1872 if (offload_usecases[offload_uc_index] == uc_id) {
1873 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001874 break;
1875 }
1876 }
1877 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1878}
1879
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001880static void *offload_thread_loop(void *context)
1881{
1882 struct stream_out *out = (struct stream_out *) context;
1883 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001884 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001886 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1887 set_sched_policy(0, SP_FOREGROUND);
1888 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1889
1890 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001891 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892 for (;;) {
1893 struct offload_cmd *cmd = NULL;
1894 stream_callback_event_t event;
1895 bool send_callback = false;
1896
1897 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1898 __func__, list_empty(&out->offload_cmd_list),
1899 out->offload_state);
1900 if (list_empty(&out->offload_cmd_list)) {
1901 ALOGV("%s SLEEPING", __func__);
1902 pthread_cond_wait(&out->offload_cond, &out->lock);
1903 ALOGV("%s RUNNING", __func__);
1904 continue;
1905 }
1906
1907 item = list_head(&out->offload_cmd_list);
1908 cmd = node_to_item(item, struct offload_cmd, node);
1909 list_remove(item);
1910
1911 ALOGVV("%s STATE %d CMD %d out->compr %p",
1912 __func__, out->offload_state, cmd->cmd, out->compr);
1913
1914 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1915 free(cmd);
1916 break;
1917 }
1918
1919 if (out->compr == NULL) {
1920 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001921 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001922 pthread_cond_signal(&out->cond);
1923 continue;
1924 }
1925 out->offload_thread_blocked = true;
1926 pthread_mutex_unlock(&out->lock);
1927 send_callback = false;
1928 switch(cmd->cmd) {
1929 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001930 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001932 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001933 send_callback = true;
1934 event = STREAM_CBK_EVENT_WRITE_READY;
1935 break;
1936 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001937 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301938 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001939 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301940 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001941 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301942 if (ret < 0)
1943 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301944 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301945 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001946 compress_drain(out->compr);
1947 else
1948 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301949 if (ret != -ENETRESET) {
1950 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301951 pthread_mutex_lock(&out->lock);
1952 out->send_new_metadata = 1;
1953 out->send_next_track_params = true;
1954 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301955 event = STREAM_CBK_EVENT_DRAIN_READY;
1956 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1957 } else
1958 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 break;
1960 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001961 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001962 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001963 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 send_callback = true;
1965 event = STREAM_CBK_EVENT_DRAIN_READY;
1966 break;
1967 default:
1968 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1969 break;
1970 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001971 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 out->offload_thread_blocked = false;
1973 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001974 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001975 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001976 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001977 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001978 free(cmd);
1979 }
1980
1981 pthread_cond_signal(&out->cond);
1982 while (!list_empty(&out->offload_cmd_list)) {
1983 item = list_head(&out->offload_cmd_list);
1984 list_remove(item);
1985 free(node_to_item(item, struct offload_cmd, node));
1986 }
1987 pthread_mutex_unlock(&out->lock);
1988
1989 return NULL;
1990}
1991
1992static int create_offload_callback_thread(struct stream_out *out)
1993{
1994 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1995 list_init(&out->offload_cmd_list);
1996 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1997 offload_thread_loop, out);
1998 return 0;
1999}
2000
2001static int destroy_offload_callback_thread(struct stream_out *out)
2002{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002003 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002004 stop_compressed_output_l(out);
2005 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2006
2007 pthread_mutex_unlock(&out->lock);
2008 pthread_join(out->offload_thread, (void **) NULL);
2009 pthread_cond_destroy(&out->offload_cond);
2010
2011 return 0;
2012}
2013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014static int stop_output_stream(struct stream_out *out)
2015{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302016 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 struct audio_usecase *uc_info;
2018 struct audio_device *adev = out->dev;
2019
Eric Laurent994a6932013-07-17 11:51:42 -07002020 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002021 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 uc_info = get_usecase_from_list(adev, out->usecase);
2023 if (uc_info == NULL) {
2024 ALOGE("%s: Could not find the usecase (%d) in the list",
2025 __func__, out->usecase);
2026 return -EINVAL;
2027 }
2028
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002029 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302030 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002031 if (adev->visualizer_stop_output != NULL)
2032 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002033
2034 audio_extn_dts_remove_state_notifier_node(out->usecase);
2035
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002036 if (adev->offload_effects_stop_output != NULL)
2037 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2038 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002039
Eric Laurent150dbfe2013-02-27 14:31:02 -08002040 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002041 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002042
2043 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002044 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002046 list_remove(&uc_info->list);
2047 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002049 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302050 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002051 ALOGV("Disable passthrough , reset mixer to pcm");
2052 /* NO_PASSTHROUGH */
2053 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002054 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002055 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2056 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002057
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302058 /* Must be called after removing the usecase from list */
2059 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302060 audio_extn_keep_alive_start();
2061
Eric Laurent994a6932013-07-17 11:51:42 -07002062 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 return ret;
2064}
2065
2066int start_output_stream(struct stream_out *out)
2067{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 struct audio_usecase *uc_info;
2070 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302071 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002073 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2074 ret = -EINVAL;
2075 goto error_config;
2076 }
2077
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302078 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2079 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2080 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302081
Naresh Tanniru80659832014-06-04 18:17:56 +05302082 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302083 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302084 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302085 goto error_config;
2086 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302087
Eric Laurentb23d5282013-05-14 15:27:20 -07002088 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 if (out->pcm_device_id < 0) {
2090 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2091 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002092 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002093 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094 }
2095
2096 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002097
2098 if (!uc_info) {
2099 ret = -ENOMEM;
2100 goto error_config;
2101 }
2102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 uc_info->id = out->usecase;
2104 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002105 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106 uc_info->devices = out->devices;
2107 uc_info->in_snd_device = SND_DEVICE_NONE;
2108 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002109 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302111 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2112 adev->perf_lock_opts,
2113 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302114
2115 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2116 audio_extn_keep_alive_stop();
2117 if (audio_extn_passthru_is_enabled() &&
2118 audio_extn_passthru_is_passthrough_stream(out)) {
2119 audio_extn_passthru_on_start(out);
2120 audio_extn_passthru_update_stream_configuration(adev, out);
2121 }
2122 }
2123
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002124 select_devices(adev, out->usecase);
2125
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002126 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2127 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002128 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002129 unsigned int flags = PCM_OUT;
2130 unsigned int pcm_open_retry_count = 0;
2131 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2132 flags |= PCM_MMAP | PCM_NOIRQ;
2133 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002134 } else if (out->realtime) {
2135 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002136 } else
2137 flags |= PCM_MONOTONIC;
2138
2139 while (1) {
2140 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2141 flags, &out->config);
2142 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2143 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2144 if (out->pcm != NULL) {
2145 pcm_close(out->pcm);
2146 out->pcm = NULL;
2147 }
2148 if (pcm_open_retry_count-- == 0) {
2149 ret = -EIO;
2150 goto error_open;
2151 }
2152 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2153 continue;
2154 }
2155 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002157
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002158 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2159 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002160
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002161 ALOGV("%s: pcm_prepare", __func__);
2162 if (pcm_is_ready(out->pcm)) {
2163 ret = pcm_prepare(out->pcm);
2164 if (ret < 0) {
2165 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2166 pcm_close(out->pcm);
2167 out->pcm = NULL;
2168 goto error_open;
2169 }
2170 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002172 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2173 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002175 out->compr = compress_open(adev->snd_card,
2176 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 COMPRESS_IN, &out->compr_config);
2178 if (out->compr && !is_compress_ready(out->compr)) {
2179 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2180 compress_close(out->compr);
2181 out->compr = NULL;
2182 ret = -EIO;
2183 goto error_open;
2184 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302185 /* compress_open sends params of the track, so reset the flag here */
2186 out->is_compr_metadata_avail = false;
2187
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002188 if (out->offload_callback)
2189 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002190
Fred Oh3f43e742015-03-04 18:42:34 -08002191 /* Since small bufs uses blocking writes, a write will be blocked
2192 for the default max poll time (20s) in the event of an SSR.
2193 Reduce the poll time to observe and deal with SSR faster.
2194 */
Ashish Jain5106d362016-05-11 19:23:33 +05302195 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002196 compress_set_max_poll_wait(out->compr, 1000);
2197 }
2198
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002199 audio_extn_dts_create_state_notifier_node(out->usecase);
2200 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2201 popcount(out->channel_mask),
2202 out->playback_started);
2203
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002204#ifdef DS1_DOLBY_DDP_ENABLED
2205 if (audio_extn_is_dolby_format(out->format))
2206 audio_extn_dolby_send_ddp_endp_params(adev);
2207#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302208 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002209 if (adev->visualizer_start_output != NULL)
2210 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2211 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302212 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002213 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002216
2217 if (ret == 0) {
2218 register_out_stream(out);
2219 if (out->realtime) {
2220 ret = pcm_start(out->pcm);
2221 if (ret < 0)
2222 goto error_open;
2223 }
2224 }
2225
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302226 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002227 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002228
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002229 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302231 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002233error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302234 /*
2235 * sleep 50ms to allow sufficient time for kernel
2236 * drivers to recover incases like SSR.
2237 */
2238 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002239 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240}
2241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242static int check_input_parameters(uint32_t sample_rate,
2243 audio_format_t format,
2244 int channel_count)
2245{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002246 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302248 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2249 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2250 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002251 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302252 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002253
2254 switch (channel_count) {
2255 case 1:
2256 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302257 case 3:
2258 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002259 case 6:
2260 break;
2261 default:
2262 ret = -EINVAL;
2263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264
2265 switch (sample_rate) {
2266 case 8000:
2267 case 11025:
2268 case 12000:
2269 case 16000:
2270 case 22050:
2271 case 24000:
2272 case 32000:
2273 case 44100:
2274 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302275 case 96000:
2276 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 break;
2278 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002279 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280 }
2281
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002282 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283}
2284
2285static size_t get_input_buffer_size(uint32_t sample_rate,
2286 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002287 int channel_count,
2288 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289{
2290 size_t size = 0;
2291
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002292 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2293 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002295 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002296 if (is_low_latency)
2297 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302298
2299 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002301 /* make sure the size is multiple of 32 bytes
2302 * At 48 kHz mono 16-bit PCM:
2303 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2304 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2305 */
2306 size += 0x1f;
2307 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002308
2309 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310}
2311
Ashish Jain058165c2016-09-28 23:18:48 +05302312static size_t get_output_period_size(uint32_t sample_rate,
2313 audio_format_t format,
2314 int channel_count,
2315 int duration /*in millisecs*/)
2316{
2317 size_t size = 0;
2318 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2319
2320 if ((duration == 0) || (sample_rate == 0) ||
2321 (bytes_per_sample == 0) || (channel_count == 0)) {
2322 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2323 bytes_per_sample, channel_count);
2324 return -EINVAL;
2325 }
2326
2327 size = (sample_rate *
2328 duration *
2329 bytes_per_sample *
2330 channel_count) / 1000;
2331 /*
2332 * To have same PCM samples for all channels, the buffer size requires to
2333 * be multiple of (number of channels * bytes per sample)
2334 * For writes to succeed, the buffer must be written at address which is multiple of 32
2335 */
2336 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2337
2338 return (size/(channel_count * bytes_per_sample));
2339}
2340
Ashish Jain5106d362016-05-11 19:23:33 +05302341static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2342{
2343 uint64_t actual_frames_rendered = 0;
2344 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2345
2346 /* This adjustment accounts for buffering after app processor.
2347 * It is based on estimated DSP latency per use case, rather than exact.
2348 */
2349 int64_t platform_latency = platform_render_latency(out->usecase) *
2350 out->sample_rate / 1000000LL;
2351
2352 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2353 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2354 * hence only estimate.
2355 */
2356 int64_t signed_frames = out->written - kernel_buffer_size;
2357
2358 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2359
2360 if (signed_frames > 0)
2361 actual_frames_rendered = signed_frames;
2362
2363 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2364 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2365 (long long int)out->written, (int)kernel_buffer_size,
2366 audio_bytes_per_sample(out->compr_config.codec->format),
2367 popcount(out->channel_mask));
2368
2369 return actual_frames_rendered;
2370}
2371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2373{
2374 struct stream_out *out = (struct stream_out *)stream;
2375
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377}
2378
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002379static int out_set_sample_rate(struct audio_stream *stream __unused,
2380 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381{
2382 return -ENOSYS;
2383}
2384
2385static size_t out_get_buffer_size(const struct audio_stream *stream)
2386{
2387 struct stream_out *out = (struct stream_out *)stream;
2388
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002389 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002391 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2392 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302393 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302394 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002396 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002397 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398}
2399
2400static uint32_t out_get_channels(const struct audio_stream *stream)
2401{
2402 struct stream_out *out = (struct stream_out *)stream;
2403
2404 return out->channel_mask;
2405}
2406
2407static audio_format_t out_get_format(const struct audio_stream *stream)
2408{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 struct stream_out *out = (struct stream_out *)stream;
2410
2411 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412}
2413
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002414static int out_set_format(struct audio_stream *stream __unused,
2415 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416{
2417 return -ENOSYS;
2418}
2419
2420static int out_standby(struct audio_stream *stream)
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302425 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2426 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002428 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002430 if (adev->adm_deregister_stream)
2431 adev->adm_deregister_stream(adev->adm_data, out->handle);
2432
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002433 if (is_offload_usecase(out->usecase))
2434 stop_compressed_output_l(out);
2435
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002436 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002438 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2439 voice_extn_compress_voip_close_output_stream(stream);
2440 pthread_mutex_unlock(&adev->lock);
2441 pthread_mutex_unlock(&out->lock);
2442 ALOGD("VOIP output entered standby");
2443 return 0;
2444 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445 if (out->pcm) {
2446 pcm_close(out->pcm);
2447 out->pcm = NULL;
2448 }
2449 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002450 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302451 out->send_next_track_params = false;
2452 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002453 out->gapless_mdata.encoder_delay = 0;
2454 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 if (out->compr != NULL) {
2456 compress_close(out->compr);
2457 out->compr = NULL;
2458 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002461 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 }
2463 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302464 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 return 0;
2466}
2467
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002468static int out_dump(const struct audio_stream *stream __unused,
2469 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470{
2471 return 0;
2472}
2473
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002474static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2475{
2476 int ret = 0;
2477 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002478
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002479 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002480 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002481 return -EINVAL;
2482 }
2483
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302484 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002485
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002486 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2487 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302488 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002489 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002490 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2491 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302492 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002493 }
2494
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002495 ALOGV("%s new encoder delay %u and padding %u", __func__,
2496 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2497
2498 return 0;
2499}
2500
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002501static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2502{
2503 return out == adev->primary_output || out == adev->voice_tx_output;
2504}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2507{
2508 struct stream_out *out = (struct stream_out *)stream;
2509 struct audio_device *adev = out->dev;
2510 struct str_parms *parms;
2511 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002512 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513
sangwoobc677242013-08-08 16:53:43 +09002514 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002515 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302517 if (!parms)
2518 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002519 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2520 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002522 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002525 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002526 * When HDMI cable is unplugged the music playback is paused and
2527 * the policy manager sends routing=0. But the audioflinger continues
2528 * to write data until standby time (3sec). As the HDMI core is
2529 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002530 * Avoid this by routing audio to speaker until standby.
2531 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002532 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2533 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302534 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002535 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2536 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302538 /*
2539 * When A2DP is disconnected the
2540 * music playback is paused and the policy manager sends routing=0
2541 * But the audioflingercontinues to write data until standby time
2542 * (3sec). As BT is turned off, the write gets blocked.
2543 * Avoid this by routing audio to speaker until standby.
2544 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002545 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302546 (val == AUDIO_DEVICE_NONE)) {
2547 val = AUDIO_DEVICE_OUT_SPEAKER;
2548 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302549 /* To avoid a2dp to sco overlapping force route BT usecases
2550 * to speaker based on Phone state
2551 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002552 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302553 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2554 (adev->mode == AUDIO_MODE_IN_CALL))) {
2555 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2556 val = AUDIO_DEVICE_OUT_SPEAKER;
2557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002558 /*
2559 * select_devices() call below switches all the usecases on the same
2560 * backend to the new device. Refer to check_usecases_codec_backend() in
2561 * the select_devices(). But how do we undo this?
2562 *
2563 * For example, music playback is active on headset (deep-buffer usecase)
2564 * and if we go to ringtones and select a ringtone, low-latency usecase
2565 * will be started on headset+speaker. As we can't enable headset+speaker
2566 * and headset devices at the same time, select_devices() switches the music
2567 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2568 * So when the ringtone playback is completed, how do we undo the same?
2569 *
2570 * We are relying on the out_set_parameters() call on deep-buffer output,
2571 * once the ringtone playback is ended.
2572 * NOTE: We should not check if the current devices are same as new devices.
2573 * Because select_devices() must be called to switch back the music
2574 * playback to headset.
2575 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002576 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002577 audio_devices_t new_dev = val;
2578 bool same_dev = out->devices == new_dev;
2579 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002580
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002581 if (output_drives_call(adev, out)) {
2582 if(!voice_is_in_call(adev)) {
2583 if (adev->mode == AUDIO_MODE_IN_CALL) {
2584 adev->current_call_output = out;
2585 ret = voice_start_call(adev);
2586 }
2587 } else {
2588 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002589 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002590 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002591 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002592
2593 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002594 if (!same_dev) {
2595 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302596 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2597 adev->perf_lock_opts,
2598 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002599 if (adev->adm_on_routing_change)
2600 adev->adm_on_routing_change(adev->adm_data,
2601 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002602 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002603 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302604 if (!same_dev)
2605 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002606 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002607 }
2608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002610 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002612
2613 if (out == adev->primary_output) {
2614 pthread_mutex_lock(&adev->lock);
2615 audio_extn_set_parameters(adev, parms);
2616 pthread_mutex_unlock(&adev->lock);
2617 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002618 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002619 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002620 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002621
2622 audio_extn_dts_create_state_notifier_node(out->usecase);
2623 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2624 popcount(out->channel_mask),
2625 out->playback_started);
2626
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002627 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002628 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002629
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302630 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2631 if (err >= 0) {
2632 strlcpy(out->profile, value, sizeof(out->profile));
2633 ALOGV("updating stream profile with value '%s'", out->profile);
2634 lock_output_stream(out);
2635 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2636 &adev->streams_output_cfg_list,
2637 out->devices, out->flags, out->format,
2638 out->sample_rate, out->bit_width,
2639 out->channel_mask, out->profile,
2640 &out->app_type_cfg);
2641 pthread_mutex_unlock(&out->lock);
2642 }
2643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302645error:
Eric Laurent994a6932013-07-17 11:51:42 -07002646 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 return ret;
2648}
2649
2650static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2651{
2652 struct stream_out *out = (struct stream_out *)stream;
2653 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002654 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 char value[256];
2656 struct str_parms *reply = str_parms_create();
2657 size_t i, j;
2658 int ret;
2659 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002660
2661 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002662 if (reply) {
2663 str_parms_destroy(reply);
2664 }
2665 if (query) {
2666 str_parms_destroy(query);
2667 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002668 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2669 return NULL;
2670 }
2671
Eric Laurent994a6932013-07-17 11:51:42 -07002672 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2674 if (ret >= 0) {
2675 value[0] = '\0';
2676 i = 0;
2677 while (out->supported_channel_masks[i] != 0) {
2678 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2679 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2680 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002681 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002683 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 first = false;
2685 break;
2686 }
2687 }
2688 i++;
2689 }
2690 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2691 str = str_parms_to_str(reply);
2692 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002693 voice_extn_out_get_parameters(out, query, reply);
2694 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002695 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002696 free(str);
2697 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002700
Alexy Joseph62142aa2015-11-16 15:10:34 -08002701
2702 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2703 if (ret >= 0) {
2704 value[0] = '\0';
2705 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2706 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302707 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002708 } else {
2709 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302710 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002711 }
2712 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002713 if (str)
2714 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002715 str = str_parms_to_str(reply);
2716 }
2717
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002718 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2719 if (ret >= 0) {
2720 value[0] = '\0';
2721 i = 0;
2722 first = true;
2723 while (out->supported_formats[i] != 0) {
2724 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2725 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2726 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002727 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002728 }
2729 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2730 first = false;
2731 break;
2732 }
2733 }
2734 i++;
2735 }
2736 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002737 if (str)
2738 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002739 str = str_parms_to_str(reply);
2740 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002741
2742 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2743 if (ret >= 0) {
2744 value[0] = '\0';
2745 i = 0;
2746 first = true;
2747 while (out->supported_sample_rates[i] != 0) {
2748 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2749 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2750 if (!first) {
2751 strlcat(value, "|", sizeof(value));
2752 }
2753 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2754 first = false;
2755 break;
2756 }
2757 }
2758 i++;
2759 }
2760 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2761 if (str)
2762 free(str);
2763 str = str_parms_to_str(reply);
2764 }
2765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 str_parms_destroy(query);
2767 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002768 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 return str;
2770}
2771
2772static uint32_t out_get_latency(const struct audio_stream_out *stream)
2773{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002774 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002776 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777
Alexy Josephaa54c872014-12-03 02:46:47 -08002778 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002779 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002780 } else if (out->realtime) {
2781 // since the buffer won't be filled up faster than realtime,
2782 // return a smaller number
2783 if (out->config.rate)
2784 period_ms = (out->af_period_multiplier * out->config.period_size *
2785 1000) / (out->config.rate);
2786 else
2787 period_ms = 0;
2788 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002789 } else {
2790 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002791 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002792 }
2793
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302794 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002795 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796}
2797
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302798static float AmpToDb(float amplification)
2799{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302800 float db = DSD_VOLUME_MIN_DB;
2801 if (amplification > 0) {
2802 db = 20 * log10(amplification);
2803 if(db < DSD_VOLUME_MIN_DB)
2804 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302805 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302806 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302807}
2808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809static int out_set_volume(struct audio_stream_out *stream, float left,
2810 float right)
2811{
Eric Laurenta9024de2013-04-04 09:19:12 -07002812 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813 int volume[2];
2814
Eric Laurenta9024de2013-04-04 09:19:12 -07002815 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2816 /* only take left channel into account: the API is for stereo anyway */
2817 out->muted = (left == 0.0f);
2818 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002819 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302820 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002821 /*
2822 * Set mute or umute on HDMI passthrough stream.
2823 * Only take left channel into account.
2824 * Mute is 0 and unmute 1
2825 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302826 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302827 } else if (out->format == AUDIO_FORMAT_DSD){
2828 char mixer_ctl_name[128] = "DSD Volume";
2829 struct audio_device *adev = out->dev;
2830 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2831
2832 if (!ctl) {
2833 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2834 __func__, mixer_ctl_name);
2835 return -EINVAL;
2836 }
2837 volume[0] = (int)(AmpToDb(left));
2838 volume[1] = (int)(AmpToDb(right));
2839 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2840 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002841 } else {
2842 char mixer_ctl_name[128];
2843 struct audio_device *adev = out->dev;
2844 struct mixer_ctl *ctl;
2845 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002846 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002848 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2849 "Compress Playback %d Volume", pcm_device_id);
2850 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2851 if (!ctl) {
2852 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2853 __func__, mixer_ctl_name);
2854 return -EINVAL;
2855 }
2856 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2857 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2858 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2859 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002861 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 return -ENOSYS;
2864}
2865
2866static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2867 size_t bytes)
2868{
2869 struct stream_out *out = (struct stream_out *)stream;
2870 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302871 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002872 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002874 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302875
Naresh Tanniru80659832014-06-04 18:17:56 +05302876 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002877
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302878 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302879 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302880 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2881 pthread_mutex_unlock(&out->lock);
2882 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302883 } else {
2884 /* increase written size during SSR to avoid mismatch
2885 * with the written frames count in AF
2886 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002887 // bytes per frame
2888 size_t bpf = audio_bytes_per_sample(out->format) *
2889 audio_channel_count_from_out_mask(out->channel_mask);
2890 if (bpf != 0)
2891 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302892 ALOGD(" %s: sound card is not active/SSR state", __func__);
2893 ret= -EIO;
2894 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302895 }
2896 }
2897
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302898 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302899 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2900 if (audio_bytes_per_sample(out->format) != 0)
2901 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2902 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302903 goto exit;
2904 }
2905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002907 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002908 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002909 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2910 ret = voice_extn_compress_voip_start_output_stream(out);
2911 else
2912 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002913 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002916 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 goto exit;
2918 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002919
2920 if (last_known_cal_step != -1) {
2921 ALOGD("%s: retry previous failed cal level set", __func__);
2922 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2923 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925
Ashish Jain81eb2a82015-05-13 10:52:34 +05302926 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002927 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302928 adev->is_channel_status_set = true;
2929 }
2930
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002931 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002932 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002933 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002934 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002935 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2936 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302937 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2938 ALOGD("copl(%p):send next track params in gapless", out);
2939 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2940 out->send_next_track_params = false;
2941 out->is_compr_metadata_avail = false;
2942 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002943 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302944 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302945 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002946
Ashish Jain83a6cc22016-06-28 14:34:17 +05302947 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302948 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302949 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302950 pthread_mutex_unlock(&out->lock);
2951 return -EINVAL;
2952 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302953 audio_format_t dst_format = out->hal_op_format;
2954 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302955
2956 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2957 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2958
Ashish Jain83a6cc22016-06-28 14:34:17 +05302959 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302960 dst_format,
2961 buffer,
2962 src_format,
2963 frames);
2964
Ashish Jain83a6cc22016-06-28 14:34:17 +05302965 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302966 bytes_to_write);
2967
2968 /*Convert written bytes in audio flinger format*/
2969 if (ret > 0)
2970 ret = ((ret * format_to_bitwidth_table[out->format]) /
2971 format_to_bitwidth_table[dst_format]);
2972 }
2973 } else
2974 ret = compress_write(out->compr, buffer, bytes);
2975
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302976 if (ret < 0)
2977 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302978 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05302979 /*msg to cb thread only if non blocking write is enabled*/
2980 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302981 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302983 } else if (-ENETRESET == ret) {
2984 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2985 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2986 pthread_mutex_unlock(&out->lock);
2987 out_standby(&out->stream.common);
2988 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002989 }
Ashish Jain5106d362016-05-11 19:23:33 +05302990 if ( ret == (ssize_t)bytes && !out->non_blocking)
2991 out->written += bytes;
2992
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05302993 /* Call compr start only when non-zero bytes of data is there to be rendered */
2994 if (!out->playback_started && ret > 0) {
2995 int status = compress_start(out->compr);
2996 if (status < 0) {
2997 ret = status;
2998 ALOGE("%s: compr start failed with err %d", __func__, errno);
2999 goto exit;
3000 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003001 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003002 out->playback_started = 1;
3003 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003004
3005 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3006 popcount(out->channel_mask),
3007 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008 }
3009 pthread_mutex_unlock(&out->lock);
3010 return ret;
3011 } else {
3012 if (out->pcm) {
3013 if (out->muted)
3014 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003015
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303016 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003017
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003018 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003019
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003020 if (out->config.rate)
3021 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3022 out->config.rate;
3023
3024 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3025
3026 request_out_focus(out, ns);
3027
3028 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003029 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003030 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303031 out->convert_buffer != NULL) {
3032
3033 memcpy_by_audio_format(out->convert_buffer,
3034 out->hal_op_format,
3035 buffer,
3036 out->hal_ip_format,
3037 out->config.period_size * out->config.channels);
3038
3039 ret = pcm_write(out->pcm, out->convert_buffer,
3040 (out->config.period_size *
3041 out->config.channels *
3042 format_to_bitwidth_table[out->hal_op_format]));
3043 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003044 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303045 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003046
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003047 release_out_focus(out);
3048
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303049 if (ret < 0)
3050 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303051 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3052 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3053 else
3054 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 }
3057
3058exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303059 /* ToDo: There may be a corner case when SSR happens back to back during
3060 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303061 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303062 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303063 }
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 pthread_mutex_unlock(&out->lock);
3066
3067 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003068 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003069 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303070 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303071 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303072 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303073 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303074 out->standby = true;
3075 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303077 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3078 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3079 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 }
3081 return bytes;
3082}
3083
3084static int out_get_render_position(const struct audio_stream_out *stream,
3085 uint32_t *dsp_frames)
3086{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303088 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003089
3090 if (dsp_frames == NULL)
3091 return -EINVAL;
3092
3093 *dsp_frames = 0;
3094 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003095 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303096
3097 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3098 * this operation and adev_close_output_stream(where out gets reset).
3099 */
3100 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3101 *dsp_frames = get_actual_pcm_frames_rendered(out);
3102 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3103 return 0;
3104 }
3105
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003106 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303107 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303108 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303110 if (ret < 0)
3111 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303113 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003114 }
3115 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303116 if (-ENETRESET == ret) {
3117 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3118 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3119 return -EINVAL;
3120 } else if(ret < 0) {
3121 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3122 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303123 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3124 /*
3125 * Handle corner case where compress session is closed during SSR
3126 * and timestamp is queried
3127 */
3128 ALOGE(" ERROR: sound card not active, return error");
3129 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303130 } else {
3131 return 0;
3132 }
Zhou Song32a556e2015-05-05 10:46:56 +08003133 } else if (audio_is_linear_pcm(out->format)) {
3134 *dsp_frames = out->written;
3135 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 } else
3137 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138}
3139
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003140static int out_add_audio_effect(const struct audio_stream *stream __unused,
3141 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142{
3143 return 0;
3144}
3145
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003146static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3147 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148{
3149 return 0;
3150}
3151
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003152static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3153 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154{
3155 return -EINVAL;
3156}
3157
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003158static int out_get_presentation_position(const struct audio_stream_out *stream,
3159 uint64_t *frames, struct timespec *timestamp)
3160{
3161 struct stream_out *out = (struct stream_out *)stream;
3162 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003163 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003164
Ashish Jain5106d362016-05-11 19:23:33 +05303165 /* below piece of code is not guarded against any lock because audioFliner serializes
3166 * this operation and adev_close_output_stream( where out gets reset).
3167 */
3168 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3169 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3170 *frames = get_actual_pcm_frames_rendered(out);
3171 /* this is the best we can do */
3172 clock_gettime(CLOCK_MONOTONIC, timestamp);
3173 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3174 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3175 return 0;
3176 }
3177
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003178 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003179
Ashish Jain5106d362016-05-11 19:23:33 +05303180 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3181 ret = compress_get_tstamp(out->compr, &dsp_frames,
3182 &out->sample_rate);
3183 ALOGVV("%s rendered frames %ld sample_rate %d",
3184 __func__, dsp_frames, out->sample_rate);
3185 *frames = dsp_frames;
3186 if (ret < 0)
3187 ret = -errno;
3188 if (-ENETRESET == ret) {
3189 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3190 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3191 ret = -EINVAL;
3192 } else
3193 ret = 0;
3194 /* this is the best we can do */
3195 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003196 } else {
3197 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003198 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003199 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3200 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003201 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003202 // This adjustment accounts for buffering after app processor.
3203 // It is based on estimated DSP latency per use case, rather than exact.
3204 signed_frames -=
3205 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3206
Eric Laurent949a0892013-09-20 09:20:13 -07003207 // It would be unusual for this value to be negative, but check just in case ...
3208 if (signed_frames >= 0) {
3209 *frames = signed_frames;
3210 ret = 0;
3211 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003212 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303213 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3214 *frames = out->written;
3215 clock_gettime(CLOCK_MONOTONIC, timestamp);
3216 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003217 }
3218 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003219 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003220 return ret;
3221}
3222
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003223static int out_set_callback(struct audio_stream_out *stream,
3224 stream_callback_t callback, void *cookie)
3225{
3226 struct stream_out *out = (struct stream_out *)stream;
3227
3228 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003229 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003230 out->offload_callback = callback;
3231 out->offload_cookie = cookie;
3232 pthread_mutex_unlock(&out->lock);
3233 return 0;
3234}
3235
3236static int out_pause(struct audio_stream_out* stream)
3237{
3238 struct stream_out *out = (struct stream_out *)stream;
3239 int status = -ENOSYS;
3240 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003241 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003242 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003243 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303245 struct audio_device *adev = out->dev;
3246 int snd_scard_state = get_snd_card_state(adev);
3247
3248 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3249 status = compress_pause(out->compr);
3250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003252
Mingming Yin21854652016-04-13 11:54:02 -07003253 if (audio_extn_passthru_is_active()) {
3254 ALOGV("offload use case, pause passthru");
3255 audio_extn_passthru_on_pause(out);
3256 }
3257
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303258 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003259 audio_extn_dts_notify_playback_state(out->usecase, 0,
3260 out->sample_rate, popcount(out->channel_mask),
3261 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 }
3263 pthread_mutex_unlock(&out->lock);
3264 }
3265 return status;
3266}
3267
3268static int out_resume(struct audio_stream_out* stream)
3269{
3270 struct stream_out *out = (struct stream_out *)stream;
3271 int status = -ENOSYS;
3272 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003273 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003274 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003276 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003277 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303278 struct audio_device *adev = out->dev;
3279 int snd_scard_state = get_snd_card_state(adev);
3280
Mingming Yin21854652016-04-13 11:54:02 -07003281 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3282 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3283 pthread_mutex_lock(&out->dev->lock);
3284 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003285 pthread_mutex_unlock(&out->dev->lock);
3286 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303287 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003288 }
3289 if (!status) {
3290 out->offload_state = OFFLOAD_STATE_PLAYING;
3291 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303292 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003293 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3294 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 }
3296 pthread_mutex_unlock(&out->lock);
3297 }
3298 return status;
3299}
3300
3301static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3302{
3303 struct stream_out *out = (struct stream_out *)stream;
3304 int status = -ENOSYS;
3305 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003306 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003307 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3309 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3310 else
3311 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3312 pthread_mutex_unlock(&out->lock);
3313 }
3314 return status;
3315}
3316
3317static int out_flush(struct audio_stream_out* stream)
3318{
3319 struct stream_out *out = (struct stream_out *)stream;
3320 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003321 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003322 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003323 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003324 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3325 stop_compressed_output_l(out);
3326 out->written = 0;
3327 } else {
3328 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3329 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003330 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003331 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332 return 0;
3333 }
3334 return -ENOSYS;
3335}
3336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337/** audio_stream_in implementation **/
3338static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3339{
3340 struct stream_in *in = (struct stream_in *)stream;
3341
3342 return in->config.rate;
3343}
3344
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003345static int in_set_sample_rate(struct audio_stream *stream __unused,
3346 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 return -ENOSYS;
3349}
3350
3351static size_t in_get_buffer_size(const struct audio_stream *stream)
3352{
3353 struct stream_in *in = (struct stream_in *)stream;
3354
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003355 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3356 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003357 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3358 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303359 else if(audio_extn_cin_attached_usecase(in->usecase))
3360 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003361
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003362 return in->config.period_size * in->af_period_multiplier *
3363 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364}
3365
3366static uint32_t in_get_channels(const struct audio_stream *stream)
3367{
3368 struct stream_in *in = (struct stream_in *)stream;
3369
3370 return in->channel_mask;
3371}
3372
3373static audio_format_t in_get_format(const struct audio_stream *stream)
3374{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003375 struct stream_in *in = (struct stream_in *)stream;
3376
3377 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378}
3379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003380static int in_set_format(struct audio_stream *stream __unused,
3381 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382{
3383 return -ENOSYS;
3384}
3385
3386static int in_standby(struct audio_stream *stream)
3387{
3388 struct stream_in *in = (struct stream_in *)stream;
3389 struct audio_device *adev = in->dev;
3390 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303391 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3392 stream, in->usecase, use_case_table[in->usecase]);
3393
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003394 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003395 if (!in->standby && in->is_st_session) {
3396 ALOGD("%s: sound trigger pcm stop lab", __func__);
3397 audio_extn_sound_trigger_stop_lab(in);
3398 in->standby = 1;
3399 }
3400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003402 if (adev->adm_deregister_stream)
3403 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3404
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003405 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003407 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3408 voice_extn_compress_voip_close_input_stream(stream);
3409 ALOGD("VOIP input entered standby");
3410 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303411 if (audio_extn_cin_attached_usecase(in->usecase))
3412 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003413 if (in->pcm) {
3414 pcm_close(in->pcm);
3415 in->pcm = NULL;
3416 }
3417 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003418 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003419 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 }
3421 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003422 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 return status;
3424}
3425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003426static int in_dump(const struct audio_stream *stream __unused,
3427 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428{
3429 return 0;
3430}
3431
3432static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3433{
3434 struct stream_in *in = (struct stream_in *)stream;
3435 struct audio_device *adev = in->dev;
3436 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003438 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303440 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 parms = str_parms_create_str(kvpairs);
3442
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303443 if (!parms)
3444 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003445 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003446 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003447
3448 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3449 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 val = atoi(value);
3451 /* no audio source uses val == 0 */
3452 if ((in->source != val) && (val != 0)) {
3453 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003454 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3455 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3456 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003457 (in->config.rate == 8000 || in->config.rate == 16000 ||
3458 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003459 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003460 err = voice_extn_compress_voip_open_input_stream(in);
3461 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003462 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003463 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003464 }
3465 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 }
3467 }
3468
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003469 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3470 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003472 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473 in->device = val;
3474 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003475 if (!in->standby && !in->is_st_session) {
3476 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003477 if (adev->adm_on_routing_change)
3478 adev->adm_on_routing_change(adev->adm_data,
3479 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003480 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482 }
3483 }
3484
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303485 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3486 if (err >= 0) {
3487 strlcpy(in->profile, value, sizeof(in->profile));
3488 ALOGV("updating stream profile with value '%s'", in->profile);
3489 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3490 &adev->streams_input_cfg_list,
3491 in->device, in->flags, in->format,
3492 in->sample_rate, in->bit_width,
3493 in->profile, &in->app_type_cfg);
3494 }
3495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003497 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498
3499 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303500error:
Eric Laurent994a6932013-07-17 11:51:42 -07003501 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 return ret;
3503}
3504
3505static char* in_get_parameters(const struct audio_stream *stream,
3506 const char *keys)
3507{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003508 struct stream_in *in = (struct stream_in *)stream;
3509 struct str_parms *query = str_parms_create_str(keys);
3510 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003511 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003512
3513 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003514 if (reply) {
3515 str_parms_destroy(reply);
3516 }
3517 if (query) {
3518 str_parms_destroy(query);
3519 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003520 ALOGE("in_get_parameters: failed to create query or reply");
3521 return NULL;
3522 }
3523
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003524 ALOGV("%s: enter: keys - %s", __func__, keys);
3525
3526 voice_extn_in_get_parameters(in, query, reply);
3527
3528 str = str_parms_to_str(reply);
3529 str_parms_destroy(query);
3530 str_parms_destroy(reply);
3531
3532 ALOGV("%s: exit: returns - %s", __func__, str);
3533 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534}
3535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003536static int in_set_gain(struct audio_stream_in *stream __unused,
3537 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
3539 return 0;
3540}
3541
3542static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3543 size_t bytes)
3544{
3545 struct stream_in *in = (struct stream_in *)stream;
3546 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303547 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303548 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303549 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003551 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303552
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003553 if (in->is_st_session) {
3554 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3555 /* Read from sound trigger HAL */
3556 audio_extn_sound_trigger_read(in, buffer, bytes);
3557 pthread_mutex_unlock(&in->lock);
3558 return bytes;
3559 }
3560
Ashish Jainbbce4322016-02-16 13:25:27 +05303561 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003562 ALOGD(" %s: sound card is not active/SSR state", __func__);
3563 ret= -EIO;;
3564 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303565 }
3566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003568 pthread_mutex_lock(&adev->lock);
3569 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3570 ret = voice_extn_compress_voip_start_input_stream(in);
3571 else
3572 ret = start_input_stream(in);
3573 pthread_mutex_unlock(&adev->lock);
3574 if (ret != 0) {
3575 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 }
3577 in->standby = 0;
3578 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003580 // what's the duration requested by the client?
3581 long ns = 0;
3582
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303583 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003584 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3585 in->config.rate;
3586
3587 request_in_focus(in, ns);
3588 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003589
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303590 if (audio_extn_cin_attached_usecase(in->usecase)) {
3591 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3592 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303593 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003594 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303595 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003596 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003597 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003598 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303599 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003600 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303601 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3602 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3603 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3604 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303605 ret = -EINVAL;
3606 goto exit;
3607 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303608 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303609 ret = -errno;
3610 }
3611 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303612 /* bytes read is always set to bytes for non compress usecases */
3613 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 }
3615
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003616 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 /*
3619 * Instead of writing zeroes here, we could trust the hardware
3620 * to always provide zeroes when muted.
3621 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303622 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3623 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 memset(buffer, 0, bytes);
3625
3626exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303627 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303628 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003629 if (-ENETRESET == ret)
3630 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 pthread_mutex_unlock(&in->lock);
3633
3634 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303635 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303636 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303637 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303638 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303639 in->standby = true;
3640 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303641 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003643 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303644 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303645 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303647 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648}
3649
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003650static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651{
3652 return 0;
3653}
3654
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003655static int add_remove_audio_effect(const struct audio_stream *stream,
3656 effect_handle_t effect,
3657 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003659 struct stream_in *in = (struct stream_in *)stream;
3660 int status = 0;
3661 effect_descriptor_t desc;
3662
3663 status = (*effect)->get_descriptor(effect, &desc);
3664 if (status != 0)
3665 return status;
3666
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003667 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003668 pthread_mutex_lock(&in->dev->lock);
3669 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3670 in->enable_aec != enable &&
3671 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3672 in->enable_aec = enable;
3673 if (!in->standby)
3674 select_devices(in->dev, in->usecase);
3675 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003676 if (in->enable_ns != enable &&
3677 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3678 in->enable_ns = enable;
3679 if (!in->standby)
3680 select_devices(in->dev, in->usecase);
3681 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003682 pthread_mutex_unlock(&in->dev->lock);
3683 pthread_mutex_unlock(&in->lock);
3684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 return 0;
3686}
3687
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003688static int in_add_audio_effect(const struct audio_stream *stream,
3689 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690{
Eric Laurent994a6932013-07-17 11:51:42 -07003691 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003692 return add_remove_audio_effect(stream, effect, true);
3693}
3694
3695static int in_remove_audio_effect(const struct audio_stream *stream,
3696 effect_handle_t effect)
3697{
Eric Laurent994a6932013-07-17 11:51:42 -07003698 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003699 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700}
3701
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303702int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 audio_io_handle_t handle,
3704 audio_devices_t devices,
3705 audio_output_flags_t flags,
3706 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003707 struct audio_stream_out **stream_out,
3708 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709{
3710 struct audio_device *adev = (struct audio_device *)dev;
3711 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303712 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003713 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303716
3717 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3718 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003719 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303720 return -EINVAL;
3721 }
3722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3724
Mingming Yin3a941d42016-02-17 18:08:05 -08003725 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3726 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303727 devices, flags, &out->stream);
3728
3729
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003730 if (!out) {
3731 return -ENOMEM;
3732 }
3733
Haynes Mathew George204045b2015-02-25 20:32:03 -08003734 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003735 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003736 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 if (devices == AUDIO_DEVICE_NONE)
3739 devices = AUDIO_DEVICE_OUT_SPEAKER;
3740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 out->flags = flags;
3742 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003743 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003744 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003745 out->sample_rate = config->sample_rate;
3746 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3747 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003748 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003749 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003750 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303751 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752
Mingming Yin3a941d42016-02-17 18:08:05 -08003753 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3754 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3755 pthread_mutex_lock(&adev->lock);
3756 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3757 ret = read_hdmi_sink_caps(out);
3758 pthread_mutex_unlock(&adev->lock);
3759 if (ret != 0) {
3760 if (ret == -ENOSYS) {
3761 /* ignore and go with default */
3762 ret = 0;
3763 } else {
3764 ALOGE("error reading hdmi sink caps");
3765 goto error_open;
3766 }
3767 }
3768 }
3769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003771 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303772 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3773 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003774 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3775 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3776
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003777 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003778 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3779 /*
3780 * Do not handle stereo output in Multi-channel cases
3781 * Stereo case is handled in normal playback path
3782 */
3783 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3784 ret = AUDIO_CHANNEL_OUT_STEREO;
3785 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003786
3787 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3788 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003789 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003790 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003791 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003792
3793 if (config->sample_rate == 0)
3794 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3795 if (config->channel_mask == 0)
3796 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003797 if (config->format == 0)
3798 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003799
3800 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003801 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003802 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3804 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003806 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003808 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3809 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003810 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003811 ret = voice_extn_compress_voip_open_output_stream(out);
3812 if (ret != 0) {
3813 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3814 __func__, ret);
3815 goto error_open;
3816 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003817 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3818 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003820 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3821 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3822 ALOGE("%s: Unsupported Offload information", __func__);
3823 ret = -EINVAL;
3824 goto error_open;
3825 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003826
Mingming Yin3a941d42016-02-17 18:08:05 -08003827 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003828 if(config->offload_info.format == 0)
3829 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003830 if (config->offload_info.sample_rate == 0)
3831 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003832 }
3833
Mingming Yin90310102013-11-13 16:57:00 -08003834 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303835 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003836 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837 ret = -EINVAL;
3838 goto error_open;
3839 }
3840
3841 out->compr_config.codec = (struct snd_codec *)
3842 calloc(1, sizeof(struct snd_codec));
3843
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003844 if (!out->compr_config.codec) {
3845 ret = -ENOMEM;
3846 goto error_open;
3847 }
3848
vivek mehta0ea887a2015-08-26 14:01:20 -07003849 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303850 out->stream.pause = out_pause;
3851 out->stream.flush = out_flush;
3852 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003853 out->usecase = get_offload_usecase(adev, true);
3854 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003855 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003856 out->stream.set_callback = out_set_callback;
3857 out->stream.pause = out_pause;
3858 out->stream.resume = out_resume;
3859 out->stream.drain = out_drain;
3860 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003861 out->usecase = get_offload_usecase(adev, false);
3862 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003863 }
vivek mehta446c3962015-09-14 10:57:35 -07003864
3865 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003866 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3867 config->format == 0 && config->sample_rate == 0 &&
3868 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003869 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003870 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3871 } else {
3872 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3873 ret = -EEXIST;
3874 goto error_open;
3875 }
vivek mehta446c3962015-09-14 10:57:35 -07003876 }
3877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003878 if (config->offload_info.channel_mask)
3879 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003880 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003881 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003882 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003883 } else {
3884 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3885 ret = -EINVAL;
3886 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003887 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003888
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003889 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003890 out->sample_rate = config->offload_info.sample_rate;
3891
Mingming Yin3ee55c62014-08-04 14:23:35 -07003892 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003893
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303894 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3895 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3896 audio_extn_dolby_send_ddp_endp_params(adev);
3897 audio_extn_dolby_set_dmid(adev);
3898 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003899
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003900 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003901 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 out->compr_config.codec->bit_rate =
3903 config->offload_info.bit_rate;
3904 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303905 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003906 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303907 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003908 /*TODO: Do we need to change it for passthrough */
3909 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910
Manish Dewangana6fc5442015-08-24 20:30:31 +05303911 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3912 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3913 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3914 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303915
3916 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3917 AUDIO_FORMAT_PCM) {
3918
3919 /*Based on platform support, configure appropriate alsa format for corresponding
3920 *hal input format.
3921 */
3922 out->compr_config.codec->format = hal_format_to_alsa(
3923 config->offload_info.format);
3924
Ashish Jain83a6cc22016-06-28 14:34:17 +05303925 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303926 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303927 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303928
3929 /*for direct PCM playback populate bit_width based on selected alsa format as
3930 *hal input format and alsa format might differ based on platform support.
3931 */
3932 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303933 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303934
3935 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3936
3937 /* Check if alsa session is configured with the same format as HAL input format,
3938 * if not then derive correct fragment size needed to accomodate the
3939 * conversion of HAL input format to alsa format.
3940 */
3941 audio_extn_utils_update_direct_pcm_fragment_size(out);
3942
3943 /*if hal input and output fragment size is different this indicates HAL input format is
3944 *not same as the alsa format
3945 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303946 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303947 /*Allocate a buffer to convert input data to the alsa configured format.
3948 *size of convert buffer is equal to the size required to hold one fragment size
3949 *worth of pcm data, this is because flinger does not write more than fragment_size
3950 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303951 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3952 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303953 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3954 ret = -ENOMEM;
3955 goto error_open;
3956 }
3957 }
3958 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3959 out->compr_config.fragment_size =
3960 audio_extn_passthru_get_buffer_size(&config->offload_info);
3961 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3962 } else {
3963 out->compr_config.fragment_size =
3964 platform_get_compress_offload_buffer_size(&config->offload_info);
3965 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3966 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003967
Amit Shekhar6f461b12014-08-01 14:52:58 -07003968 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303969 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003970
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003971 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3972 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003973
Alexy Josephaa54c872014-12-03 02:46:47 -08003974
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003975 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303976 out->send_next_track_params = false;
3977 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003978 out->offload_state = OFFLOAD_STATE_IDLE;
3979 out->playback_started = 0;
3980
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003981 audio_extn_dts_create_state_notifier_node(out->usecase);
3982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3984 __func__, config->offload_info.version,
3985 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303986
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303987 /* Check if DSD audio format is supported in codec
3988 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303989 */
3990
3991 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303992 (!platform_check_codec_dsd_support(adev->platform) ||
3993 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303994 ret = -EINVAL;
3995 goto error_open;
3996 }
3997
Ashish Jain5106d362016-05-11 19:23:33 +05303998 /* Disable gapless if any of the following is true
3999 * passthrough playback
4000 * AV playback
4001 * Direct PCM playback
4002 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304003 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304004 (config->format == AUDIO_FORMAT_DSD) ||
4005 config->offload_info.has_video ||
4006 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304007 check_and_set_gapless_mode(adev, false);
4008 } else
4009 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004010
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304011 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004012 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4013 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304014 if (config->format == AUDIO_FORMAT_DSD) {
4015 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4016 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4017 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004018
4019 create_offload_callback_thread(out);
4020
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004021 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304022 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004023 if (ret != 0) {
4024 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4025 __func__, ret);
4026 goto error_open;
4027 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004028 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4029 if (config->sample_rate == 0)
4030 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4031 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4032 config->sample_rate != 8000) {
4033 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4034 ret = -EINVAL;
4035 goto error_open;
4036 }
4037 out->sample_rate = config->sample_rate;
4038 out->config.rate = config->sample_rate;
4039 if (config->format == AUDIO_FORMAT_DEFAULT)
4040 config->format = AUDIO_FORMAT_PCM_16_BIT;
4041 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4042 config->format = AUDIO_FORMAT_PCM_16_BIT;
4043 ret = -EINVAL;
4044 goto error_open;
4045 }
4046 out->format = config->format;
4047 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4048 out->config = pcm_config_afe_proxy_playback;
4049 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004050 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304051 unsigned int channels = 0;
4052 /*Update config params to default if not set by the caller*/
4053 if (config->sample_rate == 0)
4054 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4055 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4056 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4057 if (config->format == AUDIO_FORMAT_DEFAULT)
4058 config->format = AUDIO_FORMAT_PCM_16_BIT;
4059
4060 channels = audio_channel_count_from_out_mask(out->channel_mask);
4061
Ashish Jain83a6cc22016-06-28 14:34:17 +05304062 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4063 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004064 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4065 out->flags);
4066 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304067 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4068 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4069 out->config = pcm_config_low_latency;
4070 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4071 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4072 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304073 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4074 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4075 if (out->config.period_size <= 0) {
4076 ALOGE("Invalid configuration period size is not valid");
4077 ret = -EINVAL;
4078 goto error_open;
4079 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304080 } else {
4081 /* primary path is the default path selected if no other outputs are available/suitable */
4082 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4083 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4084 }
4085 out->hal_ip_format = format = out->format;
4086 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4087 out->hal_op_format = pcm_format_to_hal(out->config.format);
4088 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4089 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004090 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304091 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304092 if (out->hal_ip_format != out->hal_op_format) {
4093 uint32_t buffer_size = out->config.period_size *
4094 format_to_bitwidth_table[out->hal_op_format] *
4095 out->config.channels;
4096 out->convert_buffer = calloc(1, buffer_size);
4097 if (out->convert_buffer == NULL){
4098 ALOGE("Allocation failed for convert buffer for size %d",
4099 out->compr_config.fragment_size);
4100 ret = -ENOMEM;
4101 goto error_open;
4102 }
4103 ALOGD("Convert buffer allocated of size %d", buffer_size);
4104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 }
4106
Ashish Jain83a6cc22016-06-28 14:34:17 +05304107 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4108 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4109
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004110 /* TODO remove this hardcoding and check why width is zero*/
4111 if (out->bit_width == 0)
4112 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304113 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004114 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004115 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304116 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304117 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004118 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4119 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4120 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004121 if(adev->primary_output == NULL)
4122 adev->primary_output = out;
4123 else {
4124 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004125 ret = -EEXIST;
4126 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004127 }
4128 }
4129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 /* Check if this usecase is already existing */
4131 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004132 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4133 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004136 ret = -EEXIST;
4137 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 }
4139 pthread_mutex_unlock(&adev->lock);
4140
4141 out->stream.common.get_sample_rate = out_get_sample_rate;
4142 out->stream.common.set_sample_rate = out_set_sample_rate;
4143 out->stream.common.get_buffer_size = out_get_buffer_size;
4144 out->stream.common.get_channels = out_get_channels;
4145 out->stream.common.get_format = out_get_format;
4146 out->stream.common.set_format = out_set_format;
4147 out->stream.common.standby = out_standby;
4148 out->stream.common.dump = out_dump;
4149 out->stream.common.set_parameters = out_set_parameters;
4150 out->stream.common.get_parameters = out_get_parameters;
4151 out->stream.common.add_audio_effect = out_add_audio_effect;
4152 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4153 out->stream.get_latency = out_get_latency;
4154 out->stream.set_volume = out_set_volume;
4155 out->stream.write = out_write;
4156 out->stream.get_render_position = out_get_render_position;
4157 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004158 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004160 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004162 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004163 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164
4165 config->format = out->stream.common.get_format(&out->stream.common);
4166 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4167 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4168
4169 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304170 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004171 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004172
4173 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4174 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4175 popcount(out->channel_mask), out->playback_started);
4176
Eric Laurent994a6932013-07-17 11:51:42 -07004177 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004179
4180error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304181 if (out->convert_buffer)
4182 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004183 free(out);
4184 *stream_out = NULL;
4185 ALOGD("%s: exit: ret %d", __func__, ret);
4186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187}
4188
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304189void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 struct audio_stream_out *stream)
4191{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004192 struct stream_out *out = (struct stream_out *)stream;
4193 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004194 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004195
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304196 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4197
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004198 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304199 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004200 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304201 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004202 if(ret != 0)
4203 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4204 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004205 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004206 out_standby(&stream->common);
4207
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004208 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004209 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004210 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004211 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004212 if (out->compr_config.codec != NULL)
4213 free(out->compr_config.codec);
4214 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004215
Ashish Jain83a6cc22016-06-28 14:34:17 +05304216 if (out->convert_buffer != NULL) {
4217 free(out->convert_buffer);
4218 out->convert_buffer = NULL;
4219 }
4220
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004221 if (adev->voice_tx_output == out)
4222 adev->voice_tx_output = NULL;
4223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004224 pthread_cond_destroy(&out->cond);
4225 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004227 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228}
4229
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004230static void close_compress_sessions(struct audio_device *adev)
4231{
Mingming Yin7b762e72015-03-04 13:47:32 -08004232 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304233 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004234 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004235 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304236
4237 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004238 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304239 if (is_offload_usecase(usecase->id)) {
4240 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004241 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4242 out = usecase->stream.out;
4243 pthread_mutex_unlock(&adev->lock);
4244 out_standby(&out->stream.common);
4245 pthread_mutex_lock(&adev->lock);
4246 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304247 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004248 }
4249 pthread_mutex_unlock(&adev->lock);
4250}
4251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4253{
4254 struct audio_device *adev = (struct audio_device *)dev;
4255 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004257 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004258 int ret;
4259 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004261 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304264 if (!parms)
4265 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004266 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4267 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304268 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304269 if (strstr(snd_card_status, "OFFLINE")) {
4270 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304271 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004272 //close compress sessions on OFFLINE status
4273 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304274 } else if (strstr(snd_card_status, "ONLINE")) {
4275 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304276 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004277 //send dts hpx license if enabled
4278 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304279 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304280 }
4281
4282 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004283 status = voice_set_parameters(adev, parms);
4284 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004285 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004287 status = platform_set_parameters(adev->platform, parms);
4288 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004289 goto done;
4290
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004291 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4292 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004293 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4295 adev->bluetooth_nrec = true;
4296 else
4297 adev->bluetooth_nrec = false;
4298 }
4299
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004300 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4301 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4303 adev->screen_off = false;
4304 else
4305 adev->screen_off = true;
4306 }
4307
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004308 ret = str_parms_get_int(parms, "rotation", &val);
4309 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004310 bool reverse_speakers = false;
4311 switch(val) {
4312 // FIXME: note that the code below assumes that the speakers are in the correct placement
4313 // relative to the user when the device is rotated 90deg from its default rotation. This
4314 // assumption is device-specific, not platform-specific like this code.
4315 case 270:
4316 reverse_speakers = true;
4317 break;
4318 case 0:
4319 case 90:
4320 case 180:
4321 break;
4322 default:
4323 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004324 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004325 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004326 if (status == 0) {
4327 if (adev->speaker_lr_swap != reverse_speakers) {
4328 adev->speaker_lr_swap = reverse_speakers;
4329 // only update the selected device if there is active pcm playback
4330 struct audio_usecase *usecase;
4331 struct listnode *node;
4332 list_for_each(node, &adev->usecase_list) {
4333 usecase = node_to_item(node, struct audio_usecase, list);
4334 if (usecase->type == PCM_PLAYBACK) {
4335 select_devices(adev, usecase->id);
4336 break;
4337 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004338 }
4339 }
4340 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004341 }
4342
Mingming Yin514a8bc2014-07-29 15:22:21 -07004343 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4344 if (ret >= 0) {
4345 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4346 adev->bt_wb_speech_enabled = true;
4347 else
4348 adev->bt_wb_speech_enabled = false;
4349 }
4350
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004351 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4352 if (ret >= 0) {
4353 val = atoi(value);
4354 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004355 ALOGV("cache new ext disp type and edid");
4356 ret = platform_get_ext_disp_type(adev->platform);
4357 if (ret < 0) {
4358 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004359 status = ret;
4360 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004361 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004362 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004363 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004364 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004365 /*
4366 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4367 * Per AudioPolicyManager, USB device is higher priority than WFD.
4368 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4369 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4370 * starting voice call on USB
4371 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004372 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4373 if (ret >= 0) {
4374 audio_extn_usb_add_device(val, atoi(value));
4375 }
vivek mehta344576a2016-04-12 18:56:03 -07004376 ALOGV("detected USB connect .. disable proxy");
4377 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004378 }
4379 }
4380
4381 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4382 if (ret >= 0) {
4383 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004384 /*
4385 * The HDMI / Displayport disconnect handling has been moved to
4386 * audio extension to ensure that its parameters are not
4387 * invalidated prior to updating sysfs of the disconnect event
4388 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4389 */
4390 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004391 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004392 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4393 if (ret >= 0) {
4394 audio_extn_usb_remove_device(val, atoi(value));
4395 }
vivek mehta344576a2016-04-12 18:56:03 -07004396 ALOGV("detected USB disconnect .. enable proxy");
4397 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004398 }
4399 }
4400
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304401 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4402 if (ret >= 0) {
4403 struct audio_usecase *usecase;
4404 struct listnode *node;
4405 list_for_each(node, &adev->usecase_list) {
4406 usecase = node_to_item(node, struct audio_usecase, list);
4407 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004408 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304409 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304410 lock_output_stream(usecase->stream.out);
4411 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304412 //force device switch to re configure encoder
4413 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304414 audio_extn_a2dp_set_handoff_mode(false);
4415 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304416 break;
4417 }
4418 }
4419 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304420 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004421done:
4422 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004423 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304424error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004425 ALOGV("%s: exit with code(%d)", __func__, status);
4426 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427}
4428
4429static char* adev_get_parameters(const struct audio_hw_device *dev,
4430 const char *keys)
4431{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004432 struct audio_device *adev = (struct audio_device *)dev;
4433 struct str_parms *reply = str_parms_create();
4434 struct str_parms *query = str_parms_create_str(keys);
4435 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304436 char value[256] = {0};
4437 int ret = 0;
4438
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004439 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004440 if (reply) {
4441 str_parms_destroy(reply);
4442 }
4443 if (query) {
4444 str_parms_destroy(query);
4445 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004446 ALOGE("adev_get_parameters: failed to create query or reply");
4447 return NULL;
4448 }
4449
Naresh Tannirud7205b62014-06-20 02:54:48 +05304450 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4451 sizeof(value));
4452 if (ret >=0) {
4453 int val = 1;
4454 pthread_mutex_lock(&adev->snd_card_status.lock);
4455 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4456 val = 0;
4457 pthread_mutex_unlock(&adev->snd_card_status.lock);
4458 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4459 goto exit;
4460 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004461
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004462 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004463 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004464 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004465 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304466 pthread_mutex_unlock(&adev->lock);
4467
Naresh Tannirud7205b62014-06-20 02:54:48 +05304468exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004469 str = str_parms_to_str(reply);
4470 str_parms_destroy(query);
4471 str_parms_destroy(reply);
4472
4473 ALOGV("%s: exit: returns - %s", __func__, str);
4474 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475}
4476
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004477static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478{
4479 return 0;
4480}
4481
4482static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4483{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004484 int ret;
4485 struct audio_device *adev = (struct audio_device *)dev;
4486 pthread_mutex_lock(&adev->lock);
4487 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004488 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004489 pthread_mutex_unlock(&adev->lock);
4490 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491}
4492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004493static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4494 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495{
4496 return -ENOSYS;
4497}
4498
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004499static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4500 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004501{
4502 return -ENOSYS;
4503}
4504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004505static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4506 bool muted __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_mute(struct audio_hw_device *dev __unused,
4512 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513{
4514 return -ENOSYS;
4515}
4516
4517static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4518{
4519 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521 pthread_mutex_lock(&adev->lock);
4522 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004523 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004525 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004526 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004527 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004528 adev->current_call_output = NULL;
4529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530 }
4531 pthread_mutex_unlock(&adev->lock);
4532 return 0;
4533}
4534
4535static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4536{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004537 int ret;
4538
4539 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004540 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004541 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4542 pthread_mutex_unlock(&adev->lock);
4543
4544 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545}
4546
4547static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4548{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004549 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 return 0;
4551}
4552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004553static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 const struct audio_config *config)
4555{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004556 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004558 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4559 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560}
4561
4562static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004563 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 audio_devices_t devices,
4565 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004566 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304567 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004568 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004569 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570{
4571 struct audio_device *adev = (struct audio_device *)dev;
4572 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004573 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004574 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004575 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304576 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304579 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4580 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583
4584 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004585
4586 if (!in) {
4587 ALOGE("failed to allocate input stream");
4588 return -ENOMEM;
4589 }
4590
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304591 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304592 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4593 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004594 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004595 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597 in->stream.common.get_sample_rate = in_get_sample_rate;
4598 in->stream.common.set_sample_rate = in_set_sample_rate;
4599 in->stream.common.get_buffer_size = in_get_buffer_size;
4600 in->stream.common.get_channels = in_get_channels;
4601 in->stream.common.get_format = in_get_format;
4602 in->stream.common.set_format = in_set_format;
4603 in->stream.common.standby = in_standby;
4604 in->stream.common.dump = in_dump;
4605 in->stream.common.set_parameters = in_set_parameters;
4606 in->stream.common.get_parameters = in_get_parameters;
4607 in->stream.common.add_audio_effect = in_add_audio_effect;
4608 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4609 in->stream.set_gain = in_set_gain;
4610 in->stream.read = in_read;
4611 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4612
4613 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004614 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 in->standby = 1;
4617 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004618 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004619 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004621 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004622 if (in->realtime) {
4623 in->config = pcm_config_audio_capture_rt;
4624 in->sample_rate = in->config.rate;
4625 in->af_period_multiplier = af_period_multiplier;
4626 } else {
4627 in->config = pcm_config_audio_capture;
4628 in->config.rate = config->sample_rate;
4629 in->sample_rate = config->sample_rate;
4630 in->af_period_multiplier = 1;
4631 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304632 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304634 /* restrict 24 bit capture for unprocessed source only
4635 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4636 */
4637 if (config->format == AUDIO_FORMAT_DEFAULT) {
4638 config->format = AUDIO_FORMAT_PCM_16_BIT;
4639 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4640 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4641 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4642 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4643 bool ret_error = false;
4644 in->bit_width = 24;
4645 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4646 from HAL is 24_packed and 8_24
4647 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4648 24_packed return error indicating supported format is 24_packed
4649 *> In case of any other source requesting 24 bit or float return error
4650 indicating format supported is 16 bit only.
4651
4652 on error flinger will retry with supported format passed
4653 */
4654 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4655 (source != AUDIO_SOURCE_CAMCORDER)) {
4656 config->format = AUDIO_FORMAT_PCM_16_BIT;
4657 if (config->sample_rate > 48000)
4658 config->sample_rate = 48000;
4659 ret_error = true;
4660 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4661 in->config.format = PCM_FORMAT_S24_3LE;
4662 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4663 in->config.format = PCM_FORMAT_S24_LE;
4664 } else {
4665 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4666 ret_error = true;
4667 }
4668
4669 if (ret_error) {
4670 ret = -EINVAL;
4671 goto err_open;
4672 }
4673 }
4674
4675 /* Update config params with the requested sample rate and channels */
4676 in->usecase = USECASE_AUDIO_RECORD;
4677 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4678 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4679 is_low_latency = true;
4680#if LOW_LATENCY_CAPTURE_USE_CASE
4681 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4682#endif
4683 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4684 }
4685
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004686 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304687 if (adev->mode != AUDIO_MODE_IN_CALL) {
4688 ret = -EINVAL;
4689 goto err_open;
4690 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004691 if (config->sample_rate == 0)
4692 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4693 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4694 config->sample_rate != 8000) {
4695 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4696 ret = -EINVAL;
4697 goto err_open;
4698 }
4699 if (config->format == AUDIO_FORMAT_DEFAULT)
4700 config->format = AUDIO_FORMAT_PCM_16_BIT;
4701 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4702 config->format = AUDIO_FORMAT_PCM_16_BIT;
4703 ret = -EINVAL;
4704 goto err_open;
4705 }
4706
4707 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4708 in->config = pcm_config_afe_proxy_record;
4709 in->config.channels = channel_count;
4710 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304711 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304712 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4713 in, config, &channel_mask_updated)) {
4714 if (channel_mask_updated == true) {
4715 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4716 __func__, config->channel_mask);
4717 ret = -EINVAL;
4718 goto err_open;
4719 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304720 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004721 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004722 audio_extn_compr_cap_format_supported(config->format) &&
4723 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004724 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304725 } else if (audio_extn_cin_applicable_stream(in)) {
4726 ret = audio_extn_cin_configure_input_stream(in);
4727 if (ret)
4728 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004729 } else {
4730 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004731 if (!in->realtime) {
4732 in->format = config->format;
4733 frame_size = audio_stream_in_frame_size(&in->stream);
4734 buffer_size = get_input_buffer_size(config->sample_rate,
4735 config->format,
4736 channel_count,
4737 is_low_latency);
4738 in->config.period_size = buffer_size / frame_size;
4739 }
4740
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004741 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4742 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4743 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004744 (in->config.rate == 8000 || in->config.rate == 16000 ||
4745 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004746 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4747 voice_extn_compress_voip_open_input_stream(in);
4748 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304751 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4752 &adev->streams_input_cfg_list,
4753 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304754 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304755
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004756 /* This stream could be for sound trigger lab,
4757 get sound trigger pcm if present */
4758 audio_extn_sound_trigger_check_and_get_session(in);
4759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004761 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004762 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763
4764err_open:
4765 free(in);
4766 *stream_in = NULL;
4767 return ret;
4768}
4769
4770static void adev_close_input_stream(struct audio_hw_device *dev,
4771 struct audio_stream_in *stream)
4772{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004773 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004774 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004775 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304776
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304777 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004778
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304779 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004780 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304781
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004782 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304783 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004784 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304785 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004786 if (ret != 0)
4787 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4788 __func__, ret);
4789 } else
4790 in_standby(&stream->common);
4791
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004792 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004793 audio_extn_ssr_deinit();
4794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304796 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004797 audio_extn_compr_cap_format_supported(in->config.format))
4798 audio_extn_compr_cap_deinit();
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304799 if (audio_extn_cin_attached_usecase(in->usecase))
4800 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004801
Mingming Yinfd7607b2016-01-22 12:48:44 -08004802 if (in->is_st_session) {
4803 ALOGV("%s: sound trigger pcm stop lab", __func__);
4804 audio_extn_sound_trigger_stop_lab(in);
4805 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004806 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807 return;
4808}
4809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004810static int adev_dump(const audio_hw_device_t *device __unused,
4811 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812{
4813 return 0;
4814}
4815
4816static int adev_close(hw_device_t *device)
4817{
4818 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004819
4820 if (!adev)
4821 return 0;
4822
4823 pthread_mutex_lock(&adev_init_lock);
4824
4825 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004826 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004827 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304828 audio_extn_utils_release_streams_cfg_lists(
4829 &adev->streams_output_cfg_list,
4830 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304831 if (audio_extn_qaf_is_enabled())
4832 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004833 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004834 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004835 free(adev->snd_dev_ref_cnt);
4836 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004837 if (adev->adm_deinit)
4838 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304839 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004840 free(device);
4841 adev = NULL;
4842 }
4843 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845 return 0;
4846}
4847
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004848/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4849 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4850 * just that it _might_ work.
4851 */
4852static int period_size_is_plausible_for_low_latency(int period_size)
4853{
4854 switch (period_size) {
4855 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004856 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004857 case 240:
4858 case 320:
4859 case 480:
4860 return 1;
4861 default:
4862 return 0;
4863 }
4864}
4865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866static int adev_open(const hw_module_t *module, const char *name,
4867 hw_device_t **device)
4868{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304869 int ret;
4870
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004871 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4873
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004874 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004875 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004876 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004877 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004878 ALOGD("%s: returning existing instance of adev", __func__);
4879 ALOGD("%s: exit", __func__);
4880 pthread_mutex_unlock(&adev_init_lock);
4881 return 0;
4882 }
4883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884 adev = calloc(1, sizeof(struct audio_device));
4885
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004886 if (!adev) {
4887 pthread_mutex_unlock(&adev_init_lock);
4888 return -ENOMEM;
4889 }
4890
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004891 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4894 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4895 adev->device.common.module = (struct hw_module_t *)module;
4896 adev->device.common.close = adev_close;
4897
4898 adev->device.init_check = adev_init_check;
4899 adev->device.set_voice_volume = adev_set_voice_volume;
4900 adev->device.set_master_volume = adev_set_master_volume;
4901 adev->device.get_master_volume = adev_get_master_volume;
4902 adev->device.set_master_mute = adev_set_master_mute;
4903 adev->device.get_master_mute = adev_get_master_mute;
4904 adev->device.set_mode = adev_set_mode;
4905 adev->device.set_mic_mute = adev_set_mic_mute;
4906 adev->device.get_mic_mute = adev_get_mic_mute;
4907 adev->device.set_parameters = adev_set_parameters;
4908 adev->device.get_parameters = adev_get_parameters;
4909 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4910 adev->device.open_output_stream = adev_open_output_stream;
4911 adev->device.close_output_stream = adev_close_output_stream;
4912 adev->device.open_input_stream = adev_open_input_stream;
4913 adev->device.close_input_stream = adev_close_input_stream;
4914 adev->device.dump = adev_dump;
4915
4916 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004918 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004919 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004922 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004923 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004924 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004925 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004926 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004927 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004928 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004929 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304930 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304931 adev->perf_lock_opts[0] = 0x101;
4932 adev->perf_lock_opts[1] = 0x20E;
4933 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304934
4935 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4936 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004937 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004938 adev->platform = platform_init(adev);
4939 if (!adev->platform) {
4940 free(adev->snd_dev_ref_cnt);
4941 free(adev);
4942 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4943 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004944 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304945 pthread_mutex_destroy(&adev->lock);
4946 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004947 return -EINVAL;
4948 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004949
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304950 if (audio_extn_qaf_is_enabled()) {
4951 ret = audio_extn_qaf_init(adev);
4952 if (ret < 0) {
4953 free(adev);
4954 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4955 *device = NULL;
4956 pthread_mutex_unlock(&adev_init_lock);
4957 pthread_mutex_destroy(&adev->lock);
4958 return ret;
4959 }
4960
4961 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
4962 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
4963 }
4964
Naresh Tanniru4c630392014-05-12 01:05:52 +05304965 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4966
Eric Laurentc4aef752013-09-12 17:45:53 -07004967 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4968 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4969 if (adev->visualizer_lib == NULL) {
4970 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4971 } else {
4972 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4973 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004974 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004975 "visualizer_hal_start_output");
4976 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004977 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004978 "visualizer_hal_stop_output");
4979 }
4980 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004981 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004982 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004983 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004984
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004985 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4986 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4987 if (adev->offload_effects_lib == NULL) {
4988 ALOGE("%s: DLOPEN failed for %s", __func__,
4989 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4990 } else {
4991 ALOGV("%s: DLOPEN successful for %s", __func__,
4992 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4993 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304994 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004995 "offload_effects_bundle_hal_start_output");
4996 adev->offload_effects_stop_output =
4997 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4998 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004999 adev->offload_effects_set_hpx_state =
5000 (int (*)(bool))dlsym(adev->offload_effects_lib,
5001 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305002 adev->offload_effects_get_parameters =
5003 (void (*)(struct str_parms *, struct str_parms *))
5004 dlsym(adev->offload_effects_lib,
5005 "offload_effects_bundle_get_parameters");
5006 adev->offload_effects_set_parameters =
5007 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5008 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005009 }
5010 }
5011
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005012 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5013 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5014 if (adev->adm_lib == NULL) {
5015 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5016 } else {
5017 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5018 adev->adm_init = (adm_init_t)
5019 dlsym(adev->adm_lib, "adm_init");
5020 adev->adm_deinit = (adm_deinit_t)
5021 dlsym(adev->adm_lib, "adm_deinit");
5022 adev->adm_register_input_stream = (adm_register_input_stream_t)
5023 dlsym(adev->adm_lib, "adm_register_input_stream");
5024 adev->adm_register_output_stream = (adm_register_output_stream_t)
5025 dlsym(adev->adm_lib, "adm_register_output_stream");
5026 adev->adm_deregister_stream = (adm_deregister_stream_t)
5027 dlsym(adev->adm_lib, "adm_deregister_stream");
5028 adev->adm_request_focus = (adm_request_focus_t)
5029 dlsym(adev->adm_lib, "adm_request_focus");
5030 adev->adm_abandon_focus = (adm_abandon_focus_t)
5031 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005032 adev->adm_set_config = (adm_set_config_t)
5033 dlsym(adev->adm_lib, "adm_set_config");
5034 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5035 dlsym(adev->adm_lib, "adm_request_focus_v2");
5036 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5037 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5038 adev->adm_on_routing_change = (adm_on_routing_change_t)
5039 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005040 }
5041 }
5042
Mingming Yin514a8bc2014-07-29 15:22:21 -07005043 adev->bt_wb_speech_enabled = false;
5044
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005045 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046 *device = &adev->device.common;
5047
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305048 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5049 &adev->streams_output_cfg_list,
5050 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005051
Kiran Kandi910e1862013-10-29 13:29:42 -07005052 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005053
5054 char value[PROPERTY_VALUE_MAX];
5055 int trial;
5056 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5057 trial = atoi(value);
5058 if (period_size_is_plausible_for_low_latency(trial)) {
5059 pcm_config_low_latency.period_size = trial;
5060 pcm_config_low_latency.start_threshold = trial / 4;
5061 pcm_config_low_latency.avail_min = trial / 4;
5062 configured_low_latency_capture_period_size = trial;
5063 }
5064 }
5065 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5066 trial = atoi(value);
5067 if (period_size_is_plausible_for_low_latency(trial)) {
5068 configured_low_latency_capture_period_size = trial;
5069 }
5070 }
5071
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005072 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5073 af_period_multiplier = atoi(value);
5074 if (af_period_multiplier < 0)
5075 af_period_multiplier = 2;
5076 else if (af_period_multiplier > 4)
5077 af_period_multiplier = 4;
5078
5079 ALOGV("new period_multiplier = %d", af_period_multiplier);
5080 }
5081
vivek mehta446c3962015-09-14 10:57:35 -07005082 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005083 pthread_mutex_unlock(&adev_init_lock);
5084
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005085 if (adev->adm_init)
5086 adev->adm_data = adev->adm_init();
5087
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305088 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305089 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005090 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091 return 0;
5092}
5093
5094static struct hw_module_methods_t hal_module_methods = {
5095 .open = adev_open,
5096};
5097
5098struct audio_module HAL_MODULE_INFO_SYM = {
5099 .common = {
5100 .tag = HARDWARE_MODULE_TAG,
5101 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5102 .hal_api_version = HARDWARE_HAL_API_VERSION,
5103 .id = AUDIO_HARDWARE_MODULE_ID,
5104 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005105 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005106 .methods = &hal_module_methods,
5107 },
5108};