blob: 8abd13be6ab26a28a49fdbdae7037842efc40579 [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
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530499 format == AUDIO_FORMAT_AAC_LC ||
500 format == AUDIO_FORMAT_AAC_HE_V1 ||
501 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530502 format == AUDIO_FORMAT_AAC_ADTS_LC ||
503 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530505 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
506 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530507 format == AUDIO_FORMAT_PCM_FLOAT ||
508 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700509 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530510 format == AUDIO_FORMAT_AC3 ||
511 format == AUDIO_FORMAT_E_AC3 ||
512 format == AUDIO_FORMAT_DTS ||
513 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800514 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530515 format == AUDIO_FORMAT_ALAC ||
516 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530517 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530518 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800519 format == AUDIO_FORMAT_WMA ||
520 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800521 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700522
523 return false;
524}
525
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700526static inline bool is_mmap_usecase(audio_usecase_t uc_id)
527{
528 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
529 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
530}
531
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530532int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530533{
534 int snd_scard_state;
535
536 if (!adev)
537 return SND_CARD_STATE_OFFLINE;
538
539 pthread_mutex_lock(&adev->snd_card_status.lock);
540 snd_scard_state = adev->snd_card_status.state;
541 pthread_mutex_unlock(&adev->snd_card_status.lock);
542
543 return snd_scard_state;
544}
545
546static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
547{
548 if (!adev)
549 return -ENOSYS;
550
551 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700552 if (adev->snd_card_status.state != snd_scard_state) {
553 adev->snd_card_status.state = snd_scard_state;
554 platform_snd_card_update(adev->platform, snd_scard_state);
555 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530556 pthread_mutex_unlock(&adev->snd_card_status.lock);
557
558 return 0;
559}
560
Avinash Vaish71a8b972014-07-24 15:36:33 +0530561static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
562 struct audio_usecase *uc_info)
563{
564 struct listnode *node;
565 struct audio_usecase *usecase;
566
567 if (uc_info == NULL)
568 return -EINVAL;
569
570 /* Re-route all voice usecases on the shared backend other than the
571 specified usecase to new snd devices */
572 list_for_each(node, &adev->usecase_list) {
573 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800574 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530575 enable_audio_route(adev, usecase);
576 }
577 return 0;
578}
579
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530580static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530581{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530582 ALOGV("%s", __func__);
583 audio_route_apply_and_update_path(adev->audio_route,
584 "asrc-mode");
585 adev->asrc_mode_enabled = true;
586}
587
588static void disable_asrc_mode(struct audio_device *adev)
589{
590 ALOGV("%s", __func__);
591 audio_route_reset_and_update_path(adev->audio_route,
592 "asrc-mode");
593 adev->asrc_mode_enabled = false;
594}
595
596/*
597 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
598 * 44.1 or Native DSD backends are enabled for any of current use case.
599 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
600 * - Disable current mix path use case(Headphone backend) and re-enable it with
601 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
602 * e.g. Naitve DSD or Headphone 44.1 -> + 48
603 */
604static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
605{
606 ALOGV("%s snd device %d", __func__, snd_device);
607 int new_backend_idx = platform_get_backend_index(snd_device);
608
609 if (((new_backend_idx == HEADPHONE_BACKEND) ||
610 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
611 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
612 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530613 struct listnode *node = NULL;
614 struct audio_usecase *uc = NULL;
615 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530616 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530617
618 list_for_each(node, &adev->usecase_list) {
619 uc = node_to_item(node, struct audio_usecase, list);
620 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530621 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530622 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
623
624 if((new_backend_idx == HEADPHONE_BACKEND) &&
625 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
626 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530627 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
628 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530629 enable_asrc_mode(adev);
630 break;
631 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
632 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
633 (usecase_backend_idx == HEADPHONE_BACKEND)) {
634 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
635 __func__);
636 disable_audio_route(adev, uc);
637 disable_snd_device(adev, uc->out_snd_device);
638 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
639 if (new_backend_idx == DSD_NATIVE_BACKEND)
640 audio_route_apply_and_update_path(adev->audio_route,
641 "hph-true-highquality-mode");
642 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
643 (curr_out->bit_width >= 24))
644 audio_route_apply_and_update_path(adev->audio_route,
645 "hph-highquality-mode");
646 enable_asrc_mode(adev);
647 enable_snd_device(adev, uc->out_snd_device);
648 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530649 break;
650 }
651 }
652 }
653 }
654}
655
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700656int pcm_ioctl(struct pcm *pcm, int request, ...)
657{
658 va_list ap;
659 void * arg;
660 int pcm_fd = *(int*)pcm;
661
662 va_start(ap, request);
663 arg = va_arg(ap, void *);
664 va_end(ap);
665
666 return ioctl(pcm_fd, request, arg);
667}
668
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700669int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700670 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700673 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800674
675 if (usecase == NULL)
676 return -EINVAL;
677
678 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
679
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800680 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800682 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800684
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800685#ifdef DS1_DOLBY_DAP_ENABLED
686 audio_extn_dolby_set_dmid(adev);
687 audio_extn_dolby_set_endpoint(adev);
688#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700689 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700690 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530691 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700692 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530693 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800694 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700695 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700696 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700697 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698 ALOGV("%s: exit", __func__);
699 return 0;
700}
701
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700702int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700703 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700706 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800707
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530708 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800709 return -EINVAL;
710
711 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 if (usecase->type == PCM_CAPTURE)
713 snd_device = usecase->in_snd_device;
714 else
715 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800716 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700717 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700718 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700719 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700720 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530721 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 ALOGV("%s: exit", __func__);
723 return 0;
724}
725
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700726int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530729 int i, num_devices = 0;
730 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700731 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
732
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 if (snd_device < SND_DEVICE_MIN ||
734 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800735 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800736 return -EINVAL;
737 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700738
739 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700740
741 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
742 ALOGE("%s: Invalid sound device returned", __func__);
743 return -EINVAL;
744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700746 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700747 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700748 return 0;
749 }
750
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530751
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700752 if (audio_extn_spkr_prot_is_enabled())
753 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700754
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800755 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
756 audio_extn_spkr_prot_is_enabled()) {
757 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700758 adev->snd_dev_ref_cnt[snd_device]--;
759 return -EINVAL;
760 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200761 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800762 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800763 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200764 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800765 return -EINVAL;
766 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700767 } else if (platform_split_snd_device(adev->platform,
768 snd_device,
769 &num_devices,
770 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530771 for (i = 0; i < num_devices; i++) {
772 enable_snd_device(adev, new_snd_devices[i]);
773 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800774 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700775 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530776
777 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
778 (audio_extn_a2dp_start_playback() < 0)) {
779 ALOGE(" fail to configure A2dp control path ");
780 return -EINVAL;
781 }
782
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700783 /* due to the possibility of calibration overwrite between listen
784 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700785 audio_extn_sound_trigger_update_device_status(snd_device,
786 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530787 audio_extn_listen_update_device_status(snd_device,
788 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700789 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700790 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700791 audio_extn_sound_trigger_update_device_status(snd_device,
792 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530793 audio_extn_listen_update_device_status(snd_device,
794 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700795 return -EINVAL;
796 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300797 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700798 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530799
800 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
801 !adev->native_playback_enabled &&
802 audio_is_true_native_stream_active(adev)) {
803 ALOGD("%s: %d: napb: enabling native mode in hardware",
804 __func__, __LINE__);
805 audio_route_apply_and_update_path(adev->audio_route,
806 "true-native-mode");
807 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530808 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810 return 0;
811}
812
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700813int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700814 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530816 int i, num_devices = 0;
817 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700818 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
819
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800820 if (snd_device < SND_DEVICE_MIN ||
821 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800822 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800823 return -EINVAL;
824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
826 ALOGE("%s: device ref cnt is already 0", __func__);
827 return -EINVAL;
828 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700829
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700831
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700832 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
833 ALOGE("%s: Invalid sound device returned", __func__);
834 return -EINVAL;
835 }
836
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700838 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530839
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800840 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
841 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700842 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700843 } else if (platform_split_snd_device(adev->platform,
844 snd_device,
845 &num_devices,
846 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530847 for (i = 0; i < num_devices; i++) {
848 disable_snd_device(adev, new_snd_devices[i]);
849 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300850 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700851 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300852 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700853
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530854 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
855 audio_extn_a2dp_stop_playback();
856
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700857 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530858 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530859 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
860 adev->native_playback_enabled) {
861 ALOGD("%s: %d: napb: disabling native mode in hardware",
862 __func__, __LINE__);
863 audio_route_reset_and_update_path(adev->audio_route,
864 "true-native-mode");
865 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530866 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
867 adev->asrc_mode_enabled) {
868 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530869 disable_asrc_mode(adev);
870 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530871 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530872
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200873 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700874 audio_extn_sound_trigger_update_device_status(snd_device,
875 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530876 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800877 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800880 return 0;
881}
882
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700883/*
884 legend:
885 uc - existing usecase
886 new_uc - new usecase
887 d1, d11, d2 - SND_DEVICE enums
888 a1, a2 - corresponding ANDROID device enums
889 B1, B2 - backend strings
890
891case 1
892 uc->dev d1 (a1) B1
893 new_uc->dev d1 (a1), d2 (a2) B1, B2
894
895 resolution: disable and enable uc->dev on d1
896
897case 2
898 uc->dev d1 (a1) B1
899 new_uc->dev d11 (a1) B1
900
901 resolution: need to switch uc since d1 and d11 are related
902 (e.g. speaker and voice-speaker)
903 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
904
905case 3
906 uc->dev d1 (a1) B1
907 new_uc->dev d2 (a2) B2
908
909 resolution: no need to switch uc
910
911case 4
912 uc->dev d1 (a1) B1
913 new_uc->dev d2 (a2) B1
914
915 resolution: disable enable uc-dev on d2 since backends match
916 we cannot enable two streams on two different devices if they
917 share the same backend. e.g. if offload is on speaker device using
918 QUAD_MI2S backend and a low-latency stream is started on voice-handset
919 using the same backend, offload must also be switched to voice-handset.
920
921case 5
922 uc->dev d1 (a1) B1
923 new_uc->dev d1 (a1), d2 (a2) B1
924
925 resolution: disable enable uc-dev on d2 since backends match
926 we cannot enable two streams on two different devices if they
927 share the same backend.
928
929case 6
930 uc->dev d1 (a1) B1
931 new_uc->dev d2 (a1) B2
932
933 resolution: no need to switch
934
935case 7
936 uc->dev d1 (a1), d2 (a2) B1, B2
937 new_uc->dev d1 (a1) B1
938
939 resolution: no need to switch
940
941*/
942static snd_device_t derive_playback_snd_device(void * platform,
943 struct audio_usecase *uc,
944 struct audio_usecase *new_uc,
945 snd_device_t new_snd_device)
946{
947 audio_devices_t a1 = uc->stream.out->devices;
948 audio_devices_t a2 = new_uc->stream.out->devices;
949
950 snd_device_t d1 = uc->out_snd_device;
951 snd_device_t d2 = new_snd_device;
952
953 // Treat as a special case when a1 and a2 are not disjoint
954 if ((a1 != a2) && (a1 & a2)) {
955 snd_device_t d3[2];
956 int num_devices = 0;
957 int ret = platform_split_snd_device(platform,
958 popcount(a1) > 1 ? d1 : d2,
959 &num_devices,
960 d3);
961 if (ret < 0) {
962 if (ret != -ENOSYS) {
963 ALOGW("%s failed to split snd_device %d",
964 __func__,
965 popcount(a1) > 1 ? d1 : d2);
966 }
967 goto end;
968 }
969
970 // NB: case 7 is hypothetical and isn't a practical usecase yet.
971 // But if it does happen, we need to give priority to d2 if
972 // the combo devices active on the existing usecase share a backend.
973 // This is because we cannot have a usecase active on a combo device
974 // and a new usecase requests one device in this combo pair.
975 if (platform_check_backends_match(d3[0], d3[1])) {
976 return d2; // case 5
977 } else {
978 return d1; // case 1
979 }
980 } else {
981 if (platform_check_backends_match(d1, d2)) {
982 return d2; // case 2, 4
983 } else {
984 return d1; // case 6, 3
985 }
986 }
987
988end:
989 return d2; // return whatever was calculated before.
990}
991
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700992static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700995{
996 struct listnode *node;
997 struct audio_usecase *usecase;
998 bool switch_device[AUDIO_USECASE_MAX];
999 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301000 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 /*
1002 * This function is to make sure that all the usecases that are active on
1003 * the hardware codec backend are always routed to any one device that is
1004 * handled by the hardware codec.
1005 * For example, if low-latency and deep-buffer usecases are currently active
1006 * on speaker and out_set_parameters(headset) is received on low-latency
1007 * output, then we have to make sure deep-buffer is also switched to headset,
1008 * because of the limitation that both the devices cannot be enabled
1009 * at the same time as they share the same backend.
1010 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001011 /*
1012 * This call is to check if we need to force routing for a particular stream
1013 * If there is a backend configuration change for the device when a
1014 * new stream starts, then ADM needs to be closed and re-opened with the new
1015 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001016 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001017 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001018 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1019 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301020 /* For a2dp device reconfigure all active sessions
1021 * with new AFE encoder format based on a2dp state
1022 */
1023 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1024 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1025 audio_extn_a2dp_is_force_device_switch()) {
1026 force_routing = true;
1027 force_restart_session = true;
1028 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301029 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1030
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001032 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001033 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1035 switch_device[i] = false;
1036
1037 list_for_each(node, &adev->usecase_list) {
1038 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001039
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301040 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1041 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301042 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301043 platform_get_snd_device_name(usecase->out_snd_device),
1044 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001045 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301046 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001047 (derive_playback_snd_device(adev->platform,
1048 usecase, uc_info,
1049 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301050 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1051 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301052 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301053 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301054 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
1055
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301056 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1057 __func__, use_case_table[usecase->id],
1058 platform_get_snd_device_name(usecase->out_snd_device));
1059 disable_audio_route(adev, usecase);
1060 switch_device[usecase->id] = true;
1061 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 }
1063 }
1064
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301065 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1066 num_uc_to_switch);
1067
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001069 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001070
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301071 /* Make sure the previous devices to be disabled first and then enable the
1072 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 list_for_each(node, &adev->usecase_list) {
1074 usecase = node_to_item(node, struct audio_usecase, list);
1075 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001076 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 }
1078 }
1079
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001080 list_for_each(node, &adev->usecase_list) {
1081 usecase = node_to_item(node, struct audio_usecase, list);
1082 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001083 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001084 }
1085 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 /* Re-route all the usecases on the shared backend other than the
1088 specified usecase to new snd devices */
1089 list_for_each(node, &adev->usecase_list) {
1090 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301091 /* Update the out_snd_device only before enabling the audio route */
1092 if (switch_device[usecase->id]) {
1093 usecase->out_snd_device = snd_device;
1094 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301096 use_case_table[usecase->id],
1097 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301098 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301099 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100 }
1101 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 }
1103}
1104
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301105static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001106 struct audio_usecase *uc_info,
1107 snd_device_t snd_device)
1108{
1109 struct listnode *node;
1110 struct audio_usecase *usecase;
1111 bool switch_device[AUDIO_USECASE_MAX];
1112 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301113 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001114
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301115 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1116 snd_device);
1117 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301118
1119 /*
1120 * Make sure out devices is checked against out codec backend device and
1121 * also in devices against in codec backend. Checking out device against in
1122 * codec backend or vice versa causes issues.
1123 */
1124 if (uc_info->type == PCM_CAPTURE)
1125 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001126 /*
1127 * This function is to make sure that all the active capture usecases
1128 * are always routed to the same input sound device.
1129 * For example, if audio-record and voice-call usecases are currently
1130 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1131 * is received for voice call then we have to make sure that audio-record
1132 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1133 * because of the limitation that two devices cannot be enabled
1134 * at the same time if they share the same backend.
1135 */
1136 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1137 switch_device[i] = false;
1138
1139 list_for_each(node, &adev->usecase_list) {
1140 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301141 /*
1142 * TODO: Enhance below condition to handle BT sco/USB multi recording
1143 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001144 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001145 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301146 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301147 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301148 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001149 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001150 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001151 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1152 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001153 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001154 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001155 switch_device[usecase->id] = true;
1156 num_uc_to_switch++;
1157 }
1158 }
1159
1160 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001161 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301163 /* Make sure the previous devices to be disabled first and then enable the
1164 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 list_for_each(node, &adev->usecase_list) {
1166 usecase = node_to_item(node, struct audio_usecase, list);
1167 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001168 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001169 }
1170 }
1171
1172 list_for_each(node, &adev->usecase_list) {
1173 usecase = node_to_item(node, struct audio_usecase, list);
1174 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001175 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001176 }
1177 }
1178
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179 /* Re-route all the usecases on the shared backend other than the
1180 specified usecase to new snd devices */
1181 list_for_each(node, &adev->usecase_list) {
1182 usecase = node_to_item(node, struct audio_usecase, list);
1183 /* Update the in_snd_device only before enabling the audio route */
1184 if (switch_device[usecase->id] ) {
1185 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001186 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301187 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001188 }
1189 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001190 }
1191}
1192
Mingming Yin3a941d42016-02-17 18:08:05 -08001193static void reset_hdmi_sink_caps(struct stream_out *out) {
1194 int i = 0;
1195
1196 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1197 out->supported_channel_masks[i] = 0;
1198 }
1199 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1200 out->supported_formats[i] = 0;
1201 }
1202 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1203 out->supported_sample_rates[i] = 0;
1204 }
1205}
1206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001208static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209{
Mingming Yin3a941d42016-02-17 18:08:05 -08001210 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001211 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212
Mingming Yin3a941d42016-02-17 18:08:05 -08001213 reset_hdmi_sink_caps(out);
1214
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001215 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001216 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001217 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001218 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001219 }
1220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001223 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001224 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001225 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1226 case 6:
1227 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1228 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1229 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1230 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1231 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1232 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233 break;
1234 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001235 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001236 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 break;
1238 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001239
1240 // check channel format caps
1241 i = 0;
1242 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1243 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1244 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1245 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1246 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1247 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1248 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1249 }
1250
1251 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1252 ALOGV(":%s HDMI supports DTS format", __func__);
1253 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1254 }
1255
1256 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1257 ALOGV(":%s HDMI supports DTS HD format", __func__);
1258 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1259 }
1260
1261
1262 // check sample rate caps
1263 i = 0;
1264 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1265 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1266 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1267 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1268 }
1269 }
1270
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001271 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272}
1273
Alexy Josephb1379942016-01-29 15:49:38 -08001274audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001275 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001276{
1277 struct audio_usecase *usecase;
1278 struct listnode *node;
1279
1280 list_for_each(node, &adev->usecase_list) {
1281 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001282 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001283 ALOGV("%s: usecase id %d", __func__, usecase->id);
1284 return usecase->id;
1285 }
1286 }
1287 return USECASE_INVALID;
1288}
1289
Alexy Josephb1379942016-01-29 15:49:38 -08001290struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001291 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292{
1293 struct audio_usecase *usecase;
1294 struct listnode *node;
1295
1296 list_for_each(node, &adev->usecase_list) {
1297 usecase = node_to_item(node, struct audio_usecase, list);
1298 if (usecase->id == uc_id)
1299 return usecase;
1300 }
1301 return NULL;
1302}
1303
Dhananjay Kumard4833242016-10-06 22:09:12 +05301304struct stream_in *get_next_active_input(const struct audio_device *adev)
1305{
1306 struct audio_usecase *usecase;
1307 struct listnode *node;
1308
1309 list_for_each_reverse(node, &adev->usecase_list) {
1310 usecase = node_to_item(node, struct audio_usecase, list);
1311 if (usecase->type == PCM_CAPTURE)
1312 return usecase->stream.in;
1313 }
1314 return NULL;
1315}
1316
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301317/*
1318 * is a true native playback active
1319 */
1320bool audio_is_true_native_stream_active(struct audio_device *adev)
1321{
1322 bool active = false;
1323 int i = 0;
1324 struct listnode *node;
1325
1326 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1327 ALOGV("%s:napb: not in true mode or non hdphones device",
1328 __func__);
1329 active = false;
1330 goto exit;
1331 }
1332
1333 list_for_each(node, &adev->usecase_list) {
1334 struct audio_usecase *uc;
1335 uc = node_to_item(node, struct audio_usecase, list);
1336 struct stream_out *curr_out =
1337 (struct stream_out*) uc->stream.out;
1338
1339 if (curr_out && PCM_PLAYBACK == uc->type) {
1340 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1341 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1342 uc->id, curr_out->sample_rate,
1343 curr_out->bit_width,
1344 platform_get_snd_device_name(uc->out_snd_device));
1345
1346 if (is_offload_usecase(uc->id) &&
1347 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1348 active = true;
1349 ALOGD("%s:napb:native stream detected", __func__);
1350 }
1351 }
1352 }
1353exit:
1354 return active;
1355}
1356
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301357/*
1358 * if native DSD playback active
1359 */
1360bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1361{
1362 bool active = false;
1363 struct listnode *node = NULL;
1364 struct audio_usecase *uc = NULL;
1365 struct stream_out *curr_out = NULL;
1366
1367 list_for_each(node, &adev->usecase_list) {
1368 uc = node_to_item(node, struct audio_usecase, list);
1369 curr_out = (struct stream_out*) uc->stream.out;
1370
1371 if (curr_out && PCM_PLAYBACK == uc->type &&
1372 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1373 active = true;
1374 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301375 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301376 }
1377 }
1378 return active;
1379}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301380
1381static bool force_device_switch(struct audio_usecase *usecase)
1382{
1383 bool ret = false;
1384 bool is_it_true_mode = false;
1385
1386 if (is_offload_usecase(usecase->id) &&
1387 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001388 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1389 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1390 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301391 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1392 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1393 (!is_it_true_mode && adev->native_playback_enabled)){
1394 ret = true;
1395 ALOGD("napb: time to toggle native mode");
1396 }
1397 }
1398
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301399 // Force all a2dp output devices to reconfigure for proper AFE encode format
1400 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001401 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301402 audio_extn_a2dp_is_force_device_switch()) {
1403 ALOGD("Force a2dp device switch to update new encoder config");
1404 ret = true;
1405 }
1406
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301407 return ret;
1408}
1409
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001410int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001412 snd_device_t out_snd_device = SND_DEVICE_NONE;
1413 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 struct audio_usecase *usecase = NULL;
1415 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001416 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001417 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001418 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001419 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1422
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001423 usecase = get_usecase_from_list(adev, uc_id);
1424 if (usecase == NULL) {
1425 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1426 return -EINVAL;
1427 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001429 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001430 (usecase->type == VOIP_CALL) ||
1431 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301432 if(usecase->stream.out == NULL) {
1433 ALOGE("%s: stream.out is NULL", __func__);
1434 return -EINVAL;
1435 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001436 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001437 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001438 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 usecase->devices = usecase->stream.out->devices;
1440 } else {
1441 /*
1442 * If the voice call is active, use the sound devices of voice call usecase
1443 * so that it would not result any device switch. All the usecases will
1444 * be switched to new device when select_devices() is called for voice call
1445 * usecase. This is to avoid switching devices for voice call when
1446 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001447 * choose voice call device only if the use case device is
1448 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001450 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001451 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001452 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001453 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1454 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301455 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1456 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001457 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 in_snd_device = vc_usecase->in_snd_device;
1459 out_snd_device = vc_usecase->out_snd_device;
1460 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001461 } else if (voice_extn_compress_voip_is_active(adev)) {
1462 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001463 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001464 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1465 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001466 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001467 in_snd_device = voip_usecase->in_snd_device;
1468 out_snd_device = voip_usecase->out_snd_device;
1469 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001470 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001471 hfp_ucid = audio_extn_hfp_get_usecase();
1472 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001473 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001474 in_snd_device = hfp_usecase->in_snd_device;
1475 out_snd_device = hfp_usecase->out_snd_device;
1476 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 }
1478 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301479 if (usecase->stream.out == NULL) {
1480 ALOGE("%s: stream.out is NULL", __func__);
1481 return -EINVAL;
1482 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 usecase->devices = usecase->stream.out->devices;
1484 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001485 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001486 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001487 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001488 if (usecase->stream.out == adev->primary_output &&
1489 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001490 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001491 select_devices(adev, adev->active_input->usecase);
1492 }
1493 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301495 if (usecase->stream.in == NULL) {
1496 ALOGE("%s: stream.in is NULL", __func__);
1497 return -EINVAL;
1498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 usecase->devices = usecase->stream.in->device;
1500 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001501 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001502 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001503 if (adev->active_input &&
1504 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301505 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1506 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1507 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001508 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001509 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001510 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1511 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001512 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001513 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001514 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 }
1516 }
1517
1518 if (out_snd_device == usecase->out_snd_device &&
1519 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301520
1521 if (!force_device_switch(usecase))
1522 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 }
1524
sangwoobc677242013-08-08 16:53:43 +09001525 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001526 out_snd_device, platform_get_snd_device_name(out_snd_device),
1527 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 /*
1530 * Limitation: While in call, to do a device switch we need to disable
1531 * and enable both RX and TX devices though one of them is same as current
1532 * device.
1533 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001534 if ((usecase->type == VOICE_CALL) &&
1535 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1536 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001537 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001538 }
1539
1540 if (((usecase->type == VOICE_CALL) ||
1541 (usecase->type == VOIP_CALL)) &&
1542 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1543 /* Disable sidetone only if voice/voip call already exists */
1544 if (voice_is_call_state_active(adev) ||
1545 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001546 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001547
1548 /* Disable aanc only if voice call exists */
1549 if (voice_is_call_state_active(adev))
1550 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001551 }
1552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 /* Disable current sound devices */
1554 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001555 disable_audio_route(adev, usecase);
1556 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557 }
1558
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001560 disable_audio_route(adev, usecase);
1561 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 }
1563
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001564 /* Applicable only on the targets that has external modem.
1565 * New device information should be sent to modem before enabling
1566 * the devices to reduce in-call device switch time.
1567 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001568 if ((usecase->type == VOICE_CALL) &&
1569 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1570 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001571 status = platform_switch_voice_call_enable_device_config(adev->platform,
1572 out_snd_device,
1573 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001574 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576 /* Enable new sound devices */
1577 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001578 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301579 if (platform_check_codec_asrc_support(adev->platform))
1580 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001581 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001584 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301585 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001586 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588
Avinash Vaish71a8b972014-07-24 15:36:33 +05301589 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001590 status = platform_switch_voice_call_device_post(adev->platform,
1591 out_snd_device,
1592 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301593 enable_audio_route_for_voice_usecases(adev, usecase);
1594 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001595
sangwoo170731f2013-06-08 15:36:36 +09001596 usecase->in_snd_device = in_snd_device;
1597 usecase->out_snd_device = out_snd_device;
1598
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301599 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1600 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301601 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001602 /* Notify device change info to effect clients registered */
1603 audio_extn_gef_notify_device_config(
1604 usecase->stream.out->devices,
1605 usecase->stream.out->channel_mask,
1606 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301607 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001608 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001609
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001610 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001611 /* Enable aanc only if voice call exists */
1612 if (voice_is_call_state_active(adev))
1613 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1614
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001615 /* Enable sidetone only if other voice/voip call already exists */
1616 if (voice_is_call_state_active(adev) ||
1617 voice_extn_compress_voip_is_started(adev))
1618 voice_set_sidetone(adev, out_snd_device, true);
1619 }
1620
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001621 /* Applicable only on the targets that has external modem.
1622 * Enable device command should be sent to modem only after
1623 * enabling voice call mixer controls
1624 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001625 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001626 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1627 out_snd_device,
1628 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301629 ALOGD("%s: done",__func__);
1630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631 return status;
1632}
1633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634static int stop_input_stream(struct stream_in *in)
1635{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301636 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 struct audio_usecase *uc_info;
1638 struct audio_device *adev = in->dev;
1639
Dhananjay Kumard4833242016-10-06 22:09:12 +05301640 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Eric Laurent994a6932013-07-17 11:51:42 -07001642 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 uc_info = get_usecase_from_list(adev, in->usecase);
1645 if (uc_info == NULL) {
1646 ALOGE("%s: Could not find the usecase (%d) in the list",
1647 __func__, in->usecase);
1648 return -EINVAL;
1649 }
1650
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001651 /* Close in-call recording streams */
1652 voice_check_and_stop_incall_rec_usecase(adev, in);
1653
Eric Laurent150dbfe2013-02-27 14:31:02 -08001654 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001655 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001656
1657 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001658 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001660 list_remove(&uc_info->list);
1661 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
Eric Laurent994a6932013-07-17 11:51:42 -07001663 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 return ret;
1665}
1666
1667int start_input_stream(struct stream_in *in)
1668{
1669 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001670 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 struct audio_usecase *uc_info;
1672 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301673 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674
Mingming Yin2664a5b2015-09-03 10:53:11 -07001675 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1676 if (get_usecase_from_list(adev, usecase) == NULL)
1677 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301678 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1679 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001680
Naresh Tanniru80659832014-06-04 18:17:56 +05301681
1682 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301683 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301684 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301685 goto error_config;
1686 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301687
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001688 /* Check if source matches incall recording usecase criteria */
1689 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1690 if (ret)
1691 goto error_config;
1692 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001693 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1694
1695 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1696 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1697 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001698 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001699 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001700
Eric Laurentb23d5282013-05-14 15:27:20 -07001701 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 if (in->pcm_device_id < 0) {
1703 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1704 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001705 ret = -EINVAL;
1706 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708
1709 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001711
1712 if (!uc_info) {
1713 ret = -ENOMEM;
1714 goto error_config;
1715 }
1716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 uc_info->id = in->usecase;
1718 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001719 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001720 uc_info->devices = in->device;
1721 uc_info->in_snd_device = SND_DEVICE_NONE;
1722 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001724 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301725 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1726 adev->perf_lock_opts,
1727 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301730 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1731 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001732
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301733 if (audio_extn_cin_attached_usecase(in->usecase)) {
1734 ret = audio_extn_cin_start_input_stream(in);
1735 if (ret)
1736 goto error_open;
1737 else
1738 goto done_open;
1739 }
1740
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001741 unsigned int flags = PCM_IN;
1742 unsigned int pcm_open_retry_count = 0;
1743
1744 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1745 flags |= PCM_MMAP | PCM_NOIRQ;
1746 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001747 } else if (in->realtime) {
1748 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001749 }
1750
1751 while (1) {
1752 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1753 flags, &in->config);
1754 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1755 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1756 if (in->pcm != NULL) {
1757 pcm_close(in->pcm);
1758 in->pcm = NULL;
1759 }
1760 if (pcm_open_retry_count-- == 0) {
1761 ret = -EIO;
1762 goto error_open;
1763 }
1764 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1765 continue;
1766 }
1767 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001769
1770 ALOGV("%s: pcm_prepare", __func__);
1771 ret = pcm_prepare(in->pcm);
1772 if (ret < 0) {
1773 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1774 pcm_close(in->pcm);
1775 in->pcm = NULL;
1776 goto error_open;
1777 }
1778
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001779 register_in_stream(in);
1780 if (in->realtime) {
1781 ret = pcm_start(in->pcm);
1782 if (ret < 0)
1783 goto error_open;
1784 }
1785
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301786done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301787 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001788 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001789
Eric Laurentc8400632013-02-14 19:04:54 -08001790 return ret;
1791
1792error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301793 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001795error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301796 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301797 /*
1798 * sleep 50ms to allow sufficient time for kernel
1799 * drivers to recover incases like SSR.
1800 */
1801 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001803
1804 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805}
1806
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001807void lock_input_stream(struct stream_in *in)
1808{
1809 pthread_mutex_lock(&in->pre_lock);
1810 pthread_mutex_lock(&in->lock);
1811 pthread_mutex_unlock(&in->pre_lock);
1812}
1813
1814void lock_output_stream(struct stream_out *out)
1815{
1816 pthread_mutex_lock(&out->pre_lock);
1817 pthread_mutex_lock(&out->lock);
1818 pthread_mutex_unlock(&out->pre_lock);
1819}
1820
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821/* must be called with out->lock locked */
1822static int send_offload_cmd_l(struct stream_out* out, int command)
1823{
1824 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1825
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001826 if (!cmd) {
1827 ALOGE("failed to allocate mem for command 0x%x", command);
1828 return -ENOMEM;
1829 }
1830
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 ALOGVV("%s %d", __func__, command);
1832
1833 cmd->cmd = command;
1834 list_add_tail(&out->offload_cmd_list, &cmd->node);
1835 pthread_cond_signal(&out->offload_cond);
1836 return 0;
1837}
1838
1839/* must be called iwth out->lock locked */
1840static void stop_compressed_output_l(struct stream_out *out)
1841{
1842 out->offload_state = OFFLOAD_STATE_IDLE;
1843 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001845 if (out->compr != NULL) {
1846 compress_stop(out->compr);
1847 while (out->offload_thread_blocked) {
1848 pthread_cond_wait(&out->cond, &out->lock);
1849 }
1850 }
1851}
1852
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001853bool is_offload_usecase(audio_usecase_t uc_id)
1854{
1855 unsigned int i;
1856 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1857 if (uc_id == offload_usecases[i])
1858 return true;
1859 }
1860 return false;
1861}
1862
vivek mehta446c3962015-09-14 10:57:35 -07001863static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001864{
vivek mehta446c3962015-09-14 10:57:35 -07001865 audio_usecase_t ret_uc = USECASE_INVALID;
1866 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001867 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001868 if (!adev->multi_offload_enable) {
1869 if (is_direct_pcm)
1870 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1871 else
1872 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001873
vivek mehta446c3962015-09-14 10:57:35 -07001874 pthread_mutex_lock(&adev->lock);
1875 if (get_usecase_from_list(adev, ret_uc) != NULL)
1876 ret_uc = USECASE_INVALID;
1877 pthread_mutex_unlock(&adev->lock);
1878
1879 return ret_uc;
1880 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001881
1882 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001883 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1884 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1885 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1886 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001887 break;
1888 }
1889 }
vivek mehta446c3962015-09-14 10:57:35 -07001890
1891 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1892 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001893}
1894
1895static void free_offload_usecase(struct audio_device *adev,
1896 audio_usecase_t uc_id)
1897{
vivek mehta446c3962015-09-14 10:57:35 -07001898 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001899 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001900
1901 if (!adev->multi_offload_enable)
1902 return;
1903
1904 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1905 if (offload_usecases[offload_uc_index] == uc_id) {
1906 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001907 break;
1908 }
1909 }
1910 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1911}
1912
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001913static void *offload_thread_loop(void *context)
1914{
1915 struct stream_out *out = (struct stream_out *) context;
1916 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001917 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001919 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1920 set_sched_policy(0, SP_FOREGROUND);
1921 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1922
1923 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001924 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001925 for (;;) {
1926 struct offload_cmd *cmd = NULL;
1927 stream_callback_event_t event;
1928 bool send_callback = false;
1929
1930 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1931 __func__, list_empty(&out->offload_cmd_list),
1932 out->offload_state);
1933 if (list_empty(&out->offload_cmd_list)) {
1934 ALOGV("%s SLEEPING", __func__);
1935 pthread_cond_wait(&out->offload_cond, &out->lock);
1936 ALOGV("%s RUNNING", __func__);
1937 continue;
1938 }
1939
1940 item = list_head(&out->offload_cmd_list);
1941 cmd = node_to_item(item, struct offload_cmd, node);
1942 list_remove(item);
1943
1944 ALOGVV("%s STATE %d CMD %d out->compr %p",
1945 __func__, out->offload_state, cmd->cmd, out->compr);
1946
1947 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1948 free(cmd);
1949 break;
1950 }
1951
1952 if (out->compr == NULL) {
1953 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001954 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001955 pthread_cond_signal(&out->cond);
1956 continue;
1957 }
1958 out->offload_thread_blocked = true;
1959 pthread_mutex_unlock(&out->lock);
1960 send_callback = false;
1961 switch(cmd->cmd) {
1962 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001963 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001965 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 send_callback = true;
1967 event = STREAM_CBK_EVENT_WRITE_READY;
1968 break;
1969 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001970 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301971 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001972 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301973 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001974 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301975 if (ret < 0)
1976 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301977 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301978 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001979 compress_drain(out->compr);
1980 else
1981 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301982 if (ret != -ENETRESET) {
1983 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301984 pthread_mutex_lock(&out->lock);
1985 out->send_new_metadata = 1;
1986 out->send_next_track_params = true;
1987 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301988 event = STREAM_CBK_EVENT_DRAIN_READY;
1989 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1990 } else
1991 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 break;
1993 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001994 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001995 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001996 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 send_callback = true;
1998 event = STREAM_CBK_EVENT_DRAIN_READY;
1999 break;
2000 default:
2001 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2002 break;
2003 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002004 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 out->offload_thread_blocked = false;
2006 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002007 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002008 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002010 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 free(cmd);
2012 }
2013
2014 pthread_cond_signal(&out->cond);
2015 while (!list_empty(&out->offload_cmd_list)) {
2016 item = list_head(&out->offload_cmd_list);
2017 list_remove(item);
2018 free(node_to_item(item, struct offload_cmd, node));
2019 }
2020 pthread_mutex_unlock(&out->lock);
2021
2022 return NULL;
2023}
2024
2025static int create_offload_callback_thread(struct stream_out *out)
2026{
2027 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2028 list_init(&out->offload_cmd_list);
2029 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2030 offload_thread_loop, out);
2031 return 0;
2032}
2033
2034static int destroy_offload_callback_thread(struct stream_out *out)
2035{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002036 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 stop_compressed_output_l(out);
2038 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2039
2040 pthread_mutex_unlock(&out->lock);
2041 pthread_join(out->offload_thread, (void **) NULL);
2042 pthread_cond_destroy(&out->offload_cond);
2043
2044 return 0;
2045}
2046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047static int stop_output_stream(struct stream_out *out)
2048{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302049 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 struct audio_usecase *uc_info;
2051 struct audio_device *adev = out->dev;
2052
Eric Laurent994a6932013-07-17 11:51:42 -07002053 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 uc_info = get_usecase_from_list(adev, out->usecase);
2056 if (uc_info == NULL) {
2057 ALOGE("%s: Could not find the usecase (%d) in the list",
2058 __func__, out->usecase);
2059 return -EINVAL;
2060 }
2061
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002062 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302063 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002064 if (adev->visualizer_stop_output != NULL)
2065 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002066
2067 audio_extn_dts_remove_state_notifier_node(out->usecase);
2068
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002069 if (adev->offload_effects_stop_output != NULL)
2070 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2071 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002072
Eric Laurent150dbfe2013-02-27 14:31:02 -08002073 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002074 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075
2076 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002077 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002079 list_remove(&uc_info->list);
2080 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002082 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302083 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002084 ALOGV("Disable passthrough , reset mixer to pcm");
2085 /* NO_PASSTHROUGH */
2086 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002087 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002088 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2089 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002090
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302091 /* Must be called after removing the usecase from list */
2092 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302093 audio_extn_keep_alive_start();
2094
Eric Laurent994a6932013-07-17 11:51:42 -07002095 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 return ret;
2097}
2098
2099int start_output_stream(struct stream_out *out)
2100{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 struct audio_usecase *uc_info;
2103 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302104 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002106 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2107 ret = -EINVAL;
2108 goto error_config;
2109 }
2110
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302111 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2112 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2113 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302114
Naresh Tanniru80659832014-06-04 18:17:56 +05302115 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302116 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302117 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302118 goto error_config;
2119 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302120
Eric Laurentb23d5282013-05-14 15:27:20 -07002121 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 if (out->pcm_device_id < 0) {
2123 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2124 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002125 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002126 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 }
2128
2129 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002130
2131 if (!uc_info) {
2132 ret = -ENOMEM;
2133 goto error_config;
2134 }
2135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 uc_info->id = out->usecase;
2137 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002138 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002139 uc_info->devices = out->devices;
2140 uc_info->in_snd_device = SND_DEVICE_NONE;
2141 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002142 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302144 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2145 adev->perf_lock_opts,
2146 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302147
2148 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2149 audio_extn_keep_alive_stop();
2150 if (audio_extn_passthru_is_enabled() &&
2151 audio_extn_passthru_is_passthrough_stream(out)) {
2152 audio_extn_passthru_on_start(out);
2153 audio_extn_passthru_update_stream_configuration(adev, out);
2154 }
2155 }
2156
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002157 select_devices(adev, out->usecase);
2158
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002159 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2160 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002161 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002162 unsigned int flags = PCM_OUT;
2163 unsigned int pcm_open_retry_count = 0;
2164 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2165 flags |= PCM_MMAP | PCM_NOIRQ;
2166 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002167 } else if (out->realtime) {
2168 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002169 } else
2170 flags |= PCM_MONOTONIC;
2171
2172 while (1) {
2173 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2174 flags, &out->config);
2175 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2176 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2177 if (out->pcm != NULL) {
2178 pcm_close(out->pcm);
2179 out->pcm = NULL;
2180 }
2181 if (pcm_open_retry_count-- == 0) {
2182 ret = -EIO;
2183 goto error_open;
2184 }
2185 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2186 continue;
2187 }
2188 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002190
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002191 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2192 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002193
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002194 ALOGV("%s: pcm_prepare", __func__);
2195 if (pcm_is_ready(out->pcm)) {
2196 ret = pcm_prepare(out->pcm);
2197 if (ret < 0) {
2198 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2199 pcm_close(out->pcm);
2200 out->pcm = NULL;
2201 goto error_open;
2202 }
2203 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002205 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2206 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002208 out->compr = compress_open(adev->snd_card,
2209 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 COMPRESS_IN, &out->compr_config);
2211 if (out->compr && !is_compress_ready(out->compr)) {
2212 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2213 compress_close(out->compr);
2214 out->compr = NULL;
2215 ret = -EIO;
2216 goto error_open;
2217 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302218 /* compress_open sends params of the track, so reset the flag here */
2219 out->is_compr_metadata_avail = false;
2220
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 if (out->offload_callback)
2222 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002223
Fred Oh3f43e742015-03-04 18:42:34 -08002224 /* Since small bufs uses blocking writes, a write will be blocked
2225 for the default max poll time (20s) in the event of an SSR.
2226 Reduce the poll time to observe and deal with SSR faster.
2227 */
Ashish Jain5106d362016-05-11 19:23:33 +05302228 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002229 compress_set_max_poll_wait(out->compr, 1000);
2230 }
2231
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002232 audio_extn_dts_create_state_notifier_node(out->usecase);
2233 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2234 popcount(out->channel_mask),
2235 out->playback_started);
2236
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002237#ifdef DS1_DOLBY_DDP_ENABLED
2238 if (audio_extn_is_dolby_format(out->format))
2239 audio_extn_dolby_send_ddp_endp_params(adev);
2240#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302241 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002242 if (adev->visualizer_start_output != NULL)
2243 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2244 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302245 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002246 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002247 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002249
2250 if (ret == 0) {
2251 register_out_stream(out);
2252 if (out->realtime) {
2253 ret = pcm_start(out->pcm);
2254 if (ret < 0)
2255 goto error_open;
2256 }
2257 }
2258
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302259 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002260 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002261
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002262 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302264 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002266error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302267 /*
2268 * sleep 50ms to allow sufficient time for kernel
2269 * drivers to recover incases like SSR.
2270 */
2271 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002272 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273}
2274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275static int check_input_parameters(uint32_t sample_rate,
2276 audio_format_t format,
2277 int channel_count)
2278{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002279 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302281 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2282 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2283 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002284 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302285 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002286
2287 switch (channel_count) {
2288 case 1:
2289 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302290 case 3:
2291 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002292 case 6:
2293 break;
2294 default:
2295 ret = -EINVAL;
2296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297
2298 switch (sample_rate) {
2299 case 8000:
2300 case 11025:
2301 case 12000:
2302 case 16000:
2303 case 22050:
2304 case 24000:
2305 case 32000:
2306 case 44100:
2307 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302308 case 96000:
2309 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 break;
2311 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002312 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 }
2314
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002315 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316}
2317
2318static size_t get_input_buffer_size(uint32_t sample_rate,
2319 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002320 int channel_count,
2321 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322{
2323 size_t size = 0;
2324
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002325 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2326 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002328 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002329 if (is_low_latency)
2330 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302331
2332 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002334 /* make sure the size is multiple of 32 bytes
2335 * At 48 kHz mono 16-bit PCM:
2336 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2337 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2338 */
2339 size += 0x1f;
2340 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002341
2342 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343}
2344
Ashish Jain058165c2016-09-28 23:18:48 +05302345static size_t get_output_period_size(uint32_t sample_rate,
2346 audio_format_t format,
2347 int channel_count,
2348 int duration /*in millisecs*/)
2349{
2350 size_t size = 0;
2351 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2352
2353 if ((duration == 0) || (sample_rate == 0) ||
2354 (bytes_per_sample == 0) || (channel_count == 0)) {
2355 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2356 bytes_per_sample, channel_count);
2357 return -EINVAL;
2358 }
2359
2360 size = (sample_rate *
2361 duration *
2362 bytes_per_sample *
2363 channel_count) / 1000;
2364 /*
2365 * To have same PCM samples for all channels, the buffer size requires to
2366 * be multiple of (number of channels * bytes per sample)
2367 * For writes to succeed, the buffer must be written at address which is multiple of 32
2368 */
2369 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2370
2371 return (size/(channel_count * bytes_per_sample));
2372}
2373
Ashish Jain5106d362016-05-11 19:23:33 +05302374static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2375{
2376 uint64_t actual_frames_rendered = 0;
2377 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2378
2379 /* This adjustment accounts for buffering after app processor.
2380 * It is based on estimated DSP latency per use case, rather than exact.
2381 */
2382 int64_t platform_latency = platform_render_latency(out->usecase) *
2383 out->sample_rate / 1000000LL;
2384
2385 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2386 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2387 * hence only estimate.
2388 */
2389 int64_t signed_frames = out->written - kernel_buffer_size;
2390
2391 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2392
2393 if (signed_frames > 0)
2394 actual_frames_rendered = signed_frames;
2395
2396 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2397 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2398 (long long int)out->written, (int)kernel_buffer_size,
2399 audio_bytes_per_sample(out->compr_config.codec->format),
2400 popcount(out->channel_mask));
2401
2402 return actual_frames_rendered;
2403}
2404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2406{
2407 struct stream_out *out = (struct stream_out *)stream;
2408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410}
2411
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002412static int out_set_sample_rate(struct audio_stream *stream __unused,
2413 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414{
2415 return -ENOSYS;
2416}
2417
2418static size_t out_get_buffer_size(const struct audio_stream *stream)
2419{
2420 struct stream_out *out = (struct stream_out *)stream;
2421
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002422 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002424 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2425 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302426 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302427 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002429 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002430 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431}
2432
2433static uint32_t out_get_channels(const struct audio_stream *stream)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436
2437 return out->channel_mask;
2438}
2439
2440static audio_format_t out_get_format(const struct audio_stream *stream)
2441{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 struct stream_out *out = (struct stream_out *)stream;
2443
2444 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445}
2446
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002447static int out_set_format(struct audio_stream *stream __unused,
2448 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449{
2450 return -ENOSYS;
2451}
2452
2453static int out_standby(struct audio_stream *stream)
2454{
2455 struct stream_out *out = (struct stream_out *)stream;
2456 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302458 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2459 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002461 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002463 if (adev->adm_deregister_stream)
2464 adev->adm_deregister_stream(adev->adm_data, out->handle);
2465
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002466 if (is_offload_usecase(out->usecase))
2467 stop_compressed_output_l(out);
2468
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002469 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002471 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2472 voice_extn_compress_voip_close_output_stream(stream);
2473 pthread_mutex_unlock(&adev->lock);
2474 pthread_mutex_unlock(&out->lock);
2475 ALOGD("VOIP output entered standby");
2476 return 0;
2477 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478 if (out->pcm) {
2479 pcm_close(out->pcm);
2480 out->pcm = NULL;
2481 }
2482 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002483 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302484 out->send_next_track_params = false;
2485 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002486 out->gapless_mdata.encoder_delay = 0;
2487 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488 if (out->compr != NULL) {
2489 compress_close(out->compr);
2490 out->compr = NULL;
2491 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002494 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 }
2496 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302497 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 return 0;
2499}
2500
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002501static int out_dump(const struct audio_stream *stream __unused,
2502 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503{
2504 return 0;
2505}
2506
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002507static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2508{
2509 int ret = 0;
2510 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002511
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002512 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002513 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002514 return -EINVAL;
2515 }
2516
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302517 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002518
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002519 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2520 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302521 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002522 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002523 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2524 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302525 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002526 }
2527
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002528 ALOGV("%s new encoder delay %u and padding %u", __func__,
2529 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2530
2531 return 0;
2532}
2533
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002534static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2535{
2536 return out == adev->primary_output || out == adev->voice_tx_output;
2537}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2540{
2541 struct stream_out *out = (struct stream_out *)stream;
2542 struct audio_device *adev = out->dev;
2543 struct str_parms *parms;
2544 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002545 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546
sangwoobc677242013-08-08 16:53:43 +09002547 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002548 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302550 if (!parms)
2551 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002552 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2553 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002555 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002556 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002558 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002559 * When HDMI cable is unplugged the music playback is paused and
2560 * the policy manager sends routing=0. But the audioflinger continues
2561 * to write data until standby time (3sec). As the HDMI core is
2562 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002563 * Avoid this by routing audio to speaker until standby.
2564 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002565 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2566 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302567 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002568 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2569 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002570 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302571 /*
2572 * When A2DP is disconnected the
2573 * music playback is paused and the policy manager sends routing=0
2574 * But the audioflingercontinues to write data until standby time
2575 * (3sec). As BT is turned off, the write gets blocked.
2576 * Avoid this by routing audio to speaker until standby.
2577 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002578 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302579 (val == AUDIO_DEVICE_NONE)) {
2580 val = AUDIO_DEVICE_OUT_SPEAKER;
2581 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302582 /* To avoid a2dp to sco overlapping force route BT usecases
2583 * to speaker based on Phone state
2584 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002585 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302586 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2587 (adev->mode == AUDIO_MODE_IN_CALL))) {
2588 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2589 val = AUDIO_DEVICE_OUT_SPEAKER;
2590 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002591 /*
2592 * select_devices() call below switches all the usecases on the same
2593 * backend to the new device. Refer to check_usecases_codec_backend() in
2594 * the select_devices(). But how do we undo this?
2595 *
2596 * For example, music playback is active on headset (deep-buffer usecase)
2597 * and if we go to ringtones and select a ringtone, low-latency usecase
2598 * will be started on headset+speaker. As we can't enable headset+speaker
2599 * and headset devices at the same time, select_devices() switches the music
2600 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2601 * So when the ringtone playback is completed, how do we undo the same?
2602 *
2603 * We are relying on the out_set_parameters() call on deep-buffer output,
2604 * once the ringtone playback is ended.
2605 * NOTE: We should not check if the current devices are same as new devices.
2606 * Because select_devices() must be called to switch back the music
2607 * playback to headset.
2608 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002609 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002610 audio_devices_t new_dev = val;
2611 bool same_dev = out->devices == new_dev;
2612 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002613
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002614 if (output_drives_call(adev, out)) {
2615 if(!voice_is_in_call(adev)) {
2616 if (adev->mode == AUDIO_MODE_IN_CALL) {
2617 adev->current_call_output = out;
2618 ret = voice_start_call(adev);
2619 }
2620 } else {
2621 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002622 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002623 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002624 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002625
2626 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002627 if (!same_dev) {
2628 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302629 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2630 adev->perf_lock_opts,
2631 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002632 if (adev->adm_on_routing_change)
2633 adev->adm_on_routing_change(adev->adm_data,
2634 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002635 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002636 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302637 if (!same_dev)
2638 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002639 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002640 }
2641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002643 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002645
2646 if (out == adev->primary_output) {
2647 pthread_mutex_lock(&adev->lock);
2648 audio_extn_set_parameters(adev, parms);
2649 pthread_mutex_unlock(&adev->lock);
2650 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002651 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002652 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002653 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002654
2655 audio_extn_dts_create_state_notifier_node(out->usecase);
2656 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2657 popcount(out->channel_mask),
2658 out->playback_started);
2659
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002660 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002661 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002662
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302663 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2664 if (err >= 0) {
2665 strlcpy(out->profile, value, sizeof(out->profile));
2666 ALOGV("updating stream profile with value '%s'", out->profile);
2667 lock_output_stream(out);
2668 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2669 &adev->streams_output_cfg_list,
2670 out->devices, out->flags, out->format,
2671 out->sample_rate, out->bit_width,
2672 out->channel_mask, out->profile,
2673 &out->app_type_cfg);
2674 pthread_mutex_unlock(&out->lock);
2675 }
2676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302678error:
Eric Laurent994a6932013-07-17 11:51:42 -07002679 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680 return ret;
2681}
2682
2683static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2684{
2685 struct stream_out *out = (struct stream_out *)stream;
2686 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002687 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 char value[256];
2689 struct str_parms *reply = str_parms_create();
2690 size_t i, j;
2691 int ret;
2692 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002693
2694 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002695 if (reply) {
2696 str_parms_destroy(reply);
2697 }
2698 if (query) {
2699 str_parms_destroy(query);
2700 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002701 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2702 return NULL;
2703 }
2704
Eric Laurent994a6932013-07-17 11:51:42 -07002705 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2707 if (ret >= 0) {
2708 value[0] = '\0';
2709 i = 0;
2710 while (out->supported_channel_masks[i] != 0) {
2711 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2712 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2713 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002714 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002716 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 first = false;
2718 break;
2719 }
2720 }
2721 i++;
2722 }
2723 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2724 str = str_parms_to_str(reply);
2725 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002726 voice_extn_out_get_parameters(out, query, reply);
2727 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002728 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002729 free(str);
2730 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002731 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002733
Alexy Joseph62142aa2015-11-16 15:10:34 -08002734
2735 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2736 if (ret >= 0) {
2737 value[0] = '\0';
2738 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2739 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302740 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002741 } else {
2742 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302743 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002744 }
2745 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002746 if (str)
2747 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002748 str = str_parms_to_str(reply);
2749 }
2750
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002751 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2752 if (ret >= 0) {
2753 value[0] = '\0';
2754 i = 0;
2755 first = true;
2756 while (out->supported_formats[i] != 0) {
2757 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2758 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2759 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002760 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002761 }
2762 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2763 first = false;
2764 break;
2765 }
2766 }
2767 i++;
2768 }
2769 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002770 if (str)
2771 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002772 str = str_parms_to_str(reply);
2773 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002774
2775 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2776 if (ret >= 0) {
2777 value[0] = '\0';
2778 i = 0;
2779 first = true;
2780 while (out->supported_sample_rates[i] != 0) {
2781 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2782 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2783 if (!first) {
2784 strlcat(value, "|", sizeof(value));
2785 }
2786 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2787 first = false;
2788 break;
2789 }
2790 }
2791 i++;
2792 }
2793 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2794 if (str)
2795 free(str);
2796 str = str_parms_to_str(reply);
2797 }
2798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 str_parms_destroy(query);
2800 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002801 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 return str;
2803}
2804
2805static uint32_t out_get_latency(const struct audio_stream_out *stream)
2806{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002807 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002809 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810
Alexy Josephaa54c872014-12-03 02:46:47 -08002811 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002812 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002813 } else if (out->realtime) {
2814 // since the buffer won't be filled up faster than realtime,
2815 // return a smaller number
2816 if (out->config.rate)
2817 period_ms = (out->af_period_multiplier * out->config.period_size *
2818 1000) / (out->config.rate);
2819 else
2820 period_ms = 0;
2821 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002822 } else {
2823 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002825 }
2826
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302827 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002828 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829}
2830
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302831static float AmpToDb(float amplification)
2832{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302833 float db = DSD_VOLUME_MIN_DB;
2834 if (amplification > 0) {
2835 db = 20 * log10(amplification);
2836 if(db < DSD_VOLUME_MIN_DB)
2837 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302838 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302839 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302840}
2841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842static int out_set_volume(struct audio_stream_out *stream, float left,
2843 float right)
2844{
Eric Laurenta9024de2013-04-04 09:19:12 -07002845 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 int volume[2];
2847
Eric Laurenta9024de2013-04-04 09:19:12 -07002848 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2849 /* only take left channel into account: the API is for stereo anyway */
2850 out->muted = (left == 0.0f);
2851 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002852 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302853 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002854 /*
2855 * Set mute or umute on HDMI passthrough stream.
2856 * Only take left channel into account.
2857 * Mute is 0 and unmute 1
2858 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302859 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302860 } else if (out->format == AUDIO_FORMAT_DSD){
2861 char mixer_ctl_name[128] = "DSD Volume";
2862 struct audio_device *adev = out->dev;
2863 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2864
2865 if (!ctl) {
2866 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2867 __func__, mixer_ctl_name);
2868 return -EINVAL;
2869 }
2870 volume[0] = (int)(AmpToDb(left));
2871 volume[1] = (int)(AmpToDb(right));
2872 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2873 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002874 } else {
2875 char mixer_ctl_name[128];
2876 struct audio_device *adev = out->dev;
2877 struct mixer_ctl *ctl;
2878 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002879 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002881 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2882 "Compress Playback %d Volume", pcm_device_id);
2883 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2884 if (!ctl) {
2885 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2886 __func__, mixer_ctl_name);
2887 return -EINVAL;
2888 }
2889 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2890 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2891 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2892 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002894 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 return -ENOSYS;
2897}
2898
2899static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2900 size_t bytes)
2901{
2902 struct stream_out *out = (struct stream_out *)stream;
2903 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302904 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002905 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002907 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302908
Naresh Tanniru80659832014-06-04 18:17:56 +05302909 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002910
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302911 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302912 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302913 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2914 pthread_mutex_unlock(&out->lock);
2915 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302916 } else {
2917 /* increase written size during SSR to avoid mismatch
2918 * with the written frames count in AF
2919 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002920 // bytes per frame
2921 size_t bpf = audio_bytes_per_sample(out->format) *
2922 audio_channel_count_from_out_mask(out->channel_mask);
2923 if (bpf != 0)
2924 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302925 ALOGD(" %s: sound card is not active/SSR state", __func__);
2926 ret= -EIO;
2927 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302928 }
2929 }
2930
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302931 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302932 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2933 if (audio_bytes_per_sample(out->format) != 0)
2934 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2935 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302936 goto exit;
2937 }
2938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002940 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002941 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002942 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2943 ret = voice_extn_compress_voip_start_output_stream(out);
2944 else
2945 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002946 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002949 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 goto exit;
2951 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002952
2953 if (last_known_cal_step != -1) {
2954 ALOGD("%s: retry previous failed cal level set", __func__);
2955 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2956 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958
Ashish Jain81eb2a82015-05-13 10:52:34 +05302959 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002960 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302961 adev->is_channel_status_set = true;
2962 }
2963
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002964 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002965 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002966 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002967 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002968 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2969 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302970 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2971 ALOGD("copl(%p):send next track params in gapless", out);
2972 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2973 out->send_next_track_params = false;
2974 out->is_compr_metadata_avail = false;
2975 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002976 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302977 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302978 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002979
Ashish Jain83a6cc22016-06-28 14:34:17 +05302980 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302981 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302982 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302983 pthread_mutex_unlock(&out->lock);
2984 return -EINVAL;
2985 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302986 audio_format_t dst_format = out->hal_op_format;
2987 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302988
2989 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2990 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2991
Ashish Jain83a6cc22016-06-28 14:34:17 +05302992 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302993 dst_format,
2994 buffer,
2995 src_format,
2996 frames);
2997
Ashish Jain83a6cc22016-06-28 14:34:17 +05302998 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302999 bytes_to_write);
3000
3001 /*Convert written bytes in audio flinger format*/
3002 if (ret > 0)
3003 ret = ((ret * format_to_bitwidth_table[out->format]) /
3004 format_to_bitwidth_table[dst_format]);
3005 }
3006 } else
3007 ret = compress_write(out->compr, buffer, bytes);
3008
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303009 if (ret < 0)
3010 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303011 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303012 /*msg to cb thread only if non blocking write is enabled*/
3013 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303014 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003015 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303016 } else if (-ENETRESET == ret) {
3017 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3018 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3019 pthread_mutex_unlock(&out->lock);
3020 out_standby(&out->stream.common);
3021 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 }
Ashish Jain5106d362016-05-11 19:23:33 +05303023 if ( ret == (ssize_t)bytes && !out->non_blocking)
3024 out->written += bytes;
3025
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303026 /* Call compr start only when non-zero bytes of data is there to be rendered */
3027 if (!out->playback_started && ret > 0) {
3028 int status = compress_start(out->compr);
3029 if (status < 0) {
3030 ret = status;
3031 ALOGE("%s: compr start failed with err %d", __func__, errno);
3032 goto exit;
3033 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003034 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003035 out->playback_started = 1;
3036 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003037
3038 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3039 popcount(out->channel_mask),
3040 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003041 }
3042 pthread_mutex_unlock(&out->lock);
3043 return ret;
3044 } else {
3045 if (out->pcm) {
3046 if (out->muted)
3047 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003048
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303049 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003050
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003051 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003052
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003053 if (out->config.rate)
3054 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3055 out->config.rate;
3056
3057 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3058
3059 request_out_focus(out, ns);
3060
3061 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003062 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003063 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303064 out->convert_buffer != NULL) {
3065
3066 memcpy_by_audio_format(out->convert_buffer,
3067 out->hal_op_format,
3068 buffer,
3069 out->hal_ip_format,
3070 out->config.period_size * out->config.channels);
3071
3072 ret = pcm_write(out->pcm, out->convert_buffer,
3073 (out->config.period_size *
3074 out->config.channels *
3075 format_to_bitwidth_table[out->hal_op_format]));
3076 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003077 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303078 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003079
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003080 release_out_focus(out);
3081
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303082 if (ret < 0)
3083 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303084 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3085 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3086 else
3087 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 }
3090
3091exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303092 /* ToDo: There may be a corner case when SSR happens back to back during
3093 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303094 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303095 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303096 }
3097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 pthread_mutex_unlock(&out->lock);
3099
3100 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003101 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003102 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303103 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303104 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303105 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303106 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303107 out->standby = true;
3108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303110 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3111 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3112 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 }
3114 return bytes;
3115}
3116
3117static int out_get_render_position(const struct audio_stream_out *stream,
3118 uint32_t *dsp_frames)
3119{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303121 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003122
3123 if (dsp_frames == NULL)
3124 return -EINVAL;
3125
3126 *dsp_frames = 0;
3127 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003128 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303129
3130 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3131 * this operation and adev_close_output_stream(where out gets reset).
3132 */
3133 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3134 *dsp_frames = get_actual_pcm_frames_rendered(out);
3135 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3136 return 0;
3137 }
3138
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003139 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303140 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303141 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303143 if (ret < 0)
3144 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303146 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003147 }
3148 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303149 if (-ENETRESET == ret) {
3150 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3151 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3152 return -EINVAL;
3153 } else if(ret < 0) {
3154 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3155 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303156 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3157 /*
3158 * Handle corner case where compress session is closed during SSR
3159 * and timestamp is queried
3160 */
3161 ALOGE(" ERROR: sound card not active, return error");
3162 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303163 } else {
3164 return 0;
3165 }
Zhou Song32a556e2015-05-05 10:46:56 +08003166 } else if (audio_is_linear_pcm(out->format)) {
3167 *dsp_frames = out->written;
3168 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 } else
3170 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171}
3172
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003173static int out_add_audio_effect(const struct audio_stream *stream __unused,
3174 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175{
3176 return 0;
3177}
3178
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003179static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3180 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181{
3182 return 0;
3183}
3184
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003185static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3186 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187{
3188 return -EINVAL;
3189}
3190
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003191static int out_get_presentation_position(const struct audio_stream_out *stream,
3192 uint64_t *frames, struct timespec *timestamp)
3193{
3194 struct stream_out *out = (struct stream_out *)stream;
3195 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003196 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003197
Ashish Jain5106d362016-05-11 19:23:33 +05303198 /* below piece of code is not guarded against any lock because audioFliner serializes
3199 * this operation and adev_close_output_stream( where out gets reset).
3200 */
3201 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3202 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3203 *frames = get_actual_pcm_frames_rendered(out);
3204 /* this is the best we can do */
3205 clock_gettime(CLOCK_MONOTONIC, timestamp);
3206 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3207 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3208 return 0;
3209 }
3210
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003211 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003212
Ashish Jain5106d362016-05-11 19:23:33 +05303213 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3214 ret = compress_get_tstamp(out->compr, &dsp_frames,
3215 &out->sample_rate);
3216 ALOGVV("%s rendered frames %ld sample_rate %d",
3217 __func__, dsp_frames, out->sample_rate);
3218 *frames = dsp_frames;
3219 if (ret < 0)
3220 ret = -errno;
3221 if (-ENETRESET == ret) {
3222 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3223 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3224 ret = -EINVAL;
3225 } else
3226 ret = 0;
3227 /* this is the best we can do */
3228 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003229 } else {
3230 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003231 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003232 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3233 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003234 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003235 // This adjustment accounts for buffering after app processor.
3236 // It is based on estimated DSP latency per use case, rather than exact.
3237 signed_frames -=
3238 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3239
Eric Laurent949a0892013-09-20 09:20:13 -07003240 // It would be unusual for this value to be negative, but check just in case ...
3241 if (signed_frames >= 0) {
3242 *frames = signed_frames;
3243 ret = 0;
3244 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003245 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303246 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3247 *frames = out->written;
3248 clock_gettime(CLOCK_MONOTONIC, timestamp);
3249 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003250 }
3251 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003252 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003253 return ret;
3254}
3255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256static int out_set_callback(struct audio_stream_out *stream,
3257 stream_callback_t callback, void *cookie)
3258{
3259 struct stream_out *out = (struct stream_out *)stream;
3260
3261 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003262 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 out->offload_callback = callback;
3264 out->offload_cookie = cookie;
3265 pthread_mutex_unlock(&out->lock);
3266 return 0;
3267}
3268
3269static int out_pause(struct audio_stream_out* stream)
3270{
3271 struct stream_out *out = (struct stream_out *)stream;
3272 int status = -ENOSYS;
3273 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003274 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003275 ALOGD("copl(%p):pause compress driver", out);
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_PLAYING) {
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
3281 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3282 status = compress_pause(out->compr);
3283
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003284 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003285
Mingming Yin21854652016-04-13 11:54:02 -07003286 if (audio_extn_passthru_is_active()) {
3287 ALOGV("offload use case, pause passthru");
3288 audio_extn_passthru_on_pause(out);
3289 }
3290
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303291 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003292 audio_extn_dts_notify_playback_state(out->usecase, 0,
3293 out->sample_rate, popcount(out->channel_mask),
3294 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 }
3296 pthread_mutex_unlock(&out->lock);
3297 }
3298 return status;
3299}
3300
3301static int out_resume(struct audio_stream_out* stream)
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)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003307 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003309 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003310 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303311 struct audio_device *adev = out->dev;
3312 int snd_scard_state = get_snd_card_state(adev);
3313
Mingming Yin21854652016-04-13 11:54:02 -07003314 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3315 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3316 pthread_mutex_lock(&out->dev->lock);
3317 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003318 pthread_mutex_unlock(&out->dev->lock);
3319 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303320 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003321 }
3322 if (!status) {
3323 out->offload_state = OFFLOAD_STATE_PLAYING;
3324 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303325 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003326 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3327 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003328 }
3329 pthread_mutex_unlock(&out->lock);
3330 }
3331 return status;
3332}
3333
3334static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3335{
3336 struct stream_out *out = (struct stream_out *)stream;
3337 int status = -ENOSYS;
3338 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003339 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003340 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003341 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3342 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3343 else
3344 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3345 pthread_mutex_unlock(&out->lock);
3346 }
3347 return status;
3348}
3349
3350static int out_flush(struct audio_stream_out* stream)
3351{
3352 struct stream_out *out = (struct stream_out *)stream;
3353 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003354 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003355 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003356 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003357 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3358 stop_compressed_output_l(out);
3359 out->written = 0;
3360 } else {
3361 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3362 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003363 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003364 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 return 0;
3366 }
3367 return -ENOSYS;
3368}
3369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370/** audio_stream_in implementation **/
3371static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3372{
3373 struct stream_in *in = (struct stream_in *)stream;
3374
3375 return in->config.rate;
3376}
3377
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003378static int in_set_sample_rate(struct audio_stream *stream __unused,
3379 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380{
3381 return -ENOSYS;
3382}
3383
3384static size_t in_get_buffer_size(const struct audio_stream *stream)
3385{
3386 struct stream_in *in = (struct stream_in *)stream;
3387
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003388 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3389 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003390 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3391 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303392 else if(audio_extn_cin_attached_usecase(in->usecase))
3393 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003394
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003395 return in->config.period_size * in->af_period_multiplier *
3396 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397}
3398
3399static uint32_t in_get_channels(const struct audio_stream *stream)
3400{
3401 struct stream_in *in = (struct stream_in *)stream;
3402
3403 return in->channel_mask;
3404}
3405
3406static audio_format_t in_get_format(const struct audio_stream *stream)
3407{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003408 struct stream_in *in = (struct stream_in *)stream;
3409
3410 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411}
3412
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003413static int in_set_format(struct audio_stream *stream __unused,
3414 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415{
3416 return -ENOSYS;
3417}
3418
3419static int in_standby(struct audio_stream *stream)
3420{
3421 struct stream_in *in = (struct stream_in *)stream;
3422 struct audio_device *adev = in->dev;
3423 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303424 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3425 stream, in->usecase, use_case_table[in->usecase]);
3426
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003427 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003428 if (!in->standby && in->is_st_session) {
3429 ALOGD("%s: sound trigger pcm stop lab", __func__);
3430 audio_extn_sound_trigger_stop_lab(in);
3431 in->standby = 1;
3432 }
3433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003435 if (adev->adm_deregister_stream)
3436 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3437
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003438 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003440 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3441 voice_extn_compress_voip_close_input_stream(stream);
3442 ALOGD("VOIP input entered standby");
3443 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303444 if (audio_extn_cin_attached_usecase(in->usecase))
3445 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003446 if (in->pcm) {
3447 pcm_close(in->pcm);
3448 in->pcm = NULL;
3449 }
3450 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003451 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003452 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 }
3454 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003455 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 return status;
3457}
3458
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003459static int in_dump(const struct audio_stream *stream __unused,
3460 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461{
3462 return 0;
3463}
3464
3465static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3466{
3467 struct stream_in *in = (struct stream_in *)stream;
3468 struct audio_device *adev = in->dev;
3469 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003471 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303473 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474 parms = str_parms_create_str(kvpairs);
3475
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303476 if (!parms)
3477 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003478 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003479 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003480
3481 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3482 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 val = atoi(value);
3484 /* no audio source uses val == 0 */
3485 if ((in->source != val) && (val != 0)) {
3486 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003487 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3488 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3489 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003490 (in->config.rate == 8000 || in->config.rate == 16000 ||
3491 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003492 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003493 err = voice_extn_compress_voip_open_input_stream(in);
3494 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003495 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003496 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003497 }
3498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 }
3500 }
3501
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003502 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3503 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003505 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 in->device = val;
3507 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003508 if (!in->standby && !in->is_st_session) {
3509 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003510 if (adev->adm_on_routing_change)
3511 adev->adm_on_routing_change(adev->adm_data,
3512 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003513 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 }
3516 }
3517
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303518 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3519 if (err >= 0) {
3520 strlcpy(in->profile, value, sizeof(in->profile));
3521 ALOGV("updating stream profile with value '%s'", in->profile);
3522 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3523 &adev->streams_input_cfg_list,
3524 in->device, in->flags, in->format,
3525 in->sample_rate, in->bit_width,
3526 in->profile, &in->app_type_cfg);
3527 }
3528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003530 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
3532 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303533error:
Eric Laurent994a6932013-07-17 11:51:42 -07003534 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 return ret;
3536}
3537
3538static char* in_get_parameters(const struct audio_stream *stream,
3539 const char *keys)
3540{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003541 struct stream_in *in = (struct stream_in *)stream;
3542 struct str_parms *query = str_parms_create_str(keys);
3543 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003544 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003545
3546 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003547 if (reply) {
3548 str_parms_destroy(reply);
3549 }
3550 if (query) {
3551 str_parms_destroy(query);
3552 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003553 ALOGE("in_get_parameters: failed to create query or reply");
3554 return NULL;
3555 }
3556
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003557 ALOGV("%s: enter: keys - %s", __func__, keys);
3558
3559 voice_extn_in_get_parameters(in, query, reply);
3560
3561 str = str_parms_to_str(reply);
3562 str_parms_destroy(query);
3563 str_parms_destroy(reply);
3564
3565 ALOGV("%s: exit: returns - %s", __func__, str);
3566 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567}
3568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003569static int in_set_gain(struct audio_stream_in *stream __unused,
3570 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571{
3572 return 0;
3573}
3574
3575static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3576 size_t bytes)
3577{
3578 struct stream_in *in = (struct stream_in *)stream;
3579 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303580 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303581 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303582 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003584 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303585
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003586 if (in->is_st_session) {
3587 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3588 /* Read from sound trigger HAL */
3589 audio_extn_sound_trigger_read(in, buffer, bytes);
3590 pthread_mutex_unlock(&in->lock);
3591 return bytes;
3592 }
3593
Ashish Jainbbce4322016-02-16 13:25:27 +05303594 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003595 ALOGD(" %s: sound card is not active/SSR state", __func__);
3596 ret= -EIO;;
3597 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303598 }
3599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003601 pthread_mutex_lock(&adev->lock);
3602 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3603 ret = voice_extn_compress_voip_start_input_stream(in);
3604 else
3605 ret = start_input_stream(in);
3606 pthread_mutex_unlock(&adev->lock);
3607 if (ret != 0) {
3608 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 }
3610 in->standby = 0;
3611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003613 // what's the duration requested by the client?
3614 long ns = 0;
3615
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303616 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003617 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3618 in->config.rate;
3619
3620 request_in_focus(in, ns);
3621 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003622
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303623 if (audio_extn_cin_attached_usecase(in->usecase)) {
3624 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3625 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303626 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003627 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303628 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003629 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003630 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003631 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303632 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003633 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303634 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3635 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3636 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3637 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303638 ret = -EINVAL;
3639 goto exit;
3640 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303641 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303642 ret = -errno;
3643 }
3644 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303645 /* bytes read is always set to bytes for non compress usecases */
3646 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003649 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 /*
3652 * Instead of writing zeroes here, we could trust the hardware
3653 * to always provide zeroes when muted.
3654 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303655 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3656 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 memset(buffer, 0, bytes);
3658
3659exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303660 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303661 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003662 if (-ENETRESET == ret)
3663 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 pthread_mutex_unlock(&in->lock);
3666
3667 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303668 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303669 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303670 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303671 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303672 in->standby = true;
3673 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303674 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003676 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303677 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303678 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303680 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681}
3682
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003683static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684{
3685 return 0;
3686}
3687
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003688static int add_remove_audio_effect(const struct audio_stream *stream,
3689 effect_handle_t effect,
3690 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003692 struct stream_in *in = (struct stream_in *)stream;
3693 int status = 0;
3694 effect_descriptor_t desc;
3695
3696 status = (*effect)->get_descriptor(effect, &desc);
3697 if (status != 0)
3698 return status;
3699
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003700 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003701 pthread_mutex_lock(&in->dev->lock);
3702 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3703 in->enable_aec != enable &&
3704 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3705 in->enable_aec = enable;
3706 if (!in->standby)
3707 select_devices(in->dev, in->usecase);
3708 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003709 if (in->enable_ns != enable &&
3710 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3711 in->enable_ns = enable;
3712 if (!in->standby)
3713 select_devices(in->dev, in->usecase);
3714 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003715 pthread_mutex_unlock(&in->dev->lock);
3716 pthread_mutex_unlock(&in->lock);
3717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 return 0;
3719}
3720
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003721static int in_add_audio_effect(const struct audio_stream *stream,
3722 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723{
Eric Laurent994a6932013-07-17 11:51:42 -07003724 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003725 return add_remove_audio_effect(stream, effect, true);
3726}
3727
3728static int in_remove_audio_effect(const struct audio_stream *stream,
3729 effect_handle_t effect)
3730{
Eric Laurent994a6932013-07-17 11:51:42 -07003731 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003732 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733}
3734
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303735int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 audio_io_handle_t handle,
3737 audio_devices_t devices,
3738 audio_output_flags_t flags,
3739 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003740 struct audio_stream_out **stream_out,
3741 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742{
3743 struct audio_device *adev = (struct audio_device *)dev;
3744 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303745 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003746 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303749
3750 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3751 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003752 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303753 return -EINVAL;
3754 }
3755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3757
Mingming Yin3a941d42016-02-17 18:08:05 -08003758 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3759 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303760 devices, flags, &out->stream);
3761
3762
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003763 if (!out) {
3764 return -ENOMEM;
3765 }
3766
Haynes Mathew George204045b2015-02-25 20:32:03 -08003767 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003768 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003769 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 if (devices == AUDIO_DEVICE_NONE)
3772 devices = AUDIO_DEVICE_OUT_SPEAKER;
3773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 out->flags = flags;
3775 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003776 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003777 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003778 out->sample_rate = config->sample_rate;
3779 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3780 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003781 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003782 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003783 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303784 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785
Mingming Yin3a941d42016-02-17 18:08:05 -08003786 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3787 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3788 pthread_mutex_lock(&adev->lock);
3789 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3790 ret = read_hdmi_sink_caps(out);
3791 pthread_mutex_unlock(&adev->lock);
3792 if (ret != 0) {
3793 if (ret == -ENOSYS) {
3794 /* ignore and go with default */
3795 ret = 0;
3796 } else {
3797 ALOGE("error reading hdmi sink caps");
3798 goto error_open;
3799 }
3800 }
3801 }
3802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003804 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303805 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3806 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003807 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3808 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3809
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003810 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003811 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3812 /*
3813 * Do not handle stereo output in Multi-channel cases
3814 * Stereo case is handled in normal playback path
3815 */
3816 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3817 ret = AUDIO_CHANNEL_OUT_STEREO;
3818 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003819
3820 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3821 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003822 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003823 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003824 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003825
3826 if (config->sample_rate == 0)
3827 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3828 if (config->channel_mask == 0)
3829 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003830 if (config->format == 0)
3831 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003832
3833 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003834 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003835 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3837 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003839 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003841 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3842 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003843 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003844 ret = voice_extn_compress_voip_open_output_stream(out);
3845 if (ret != 0) {
3846 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3847 __func__, ret);
3848 goto error_open;
3849 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003850 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3851 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3852
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3854 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3855 ALOGE("%s: Unsupported Offload information", __func__);
3856 ret = -EINVAL;
3857 goto error_open;
3858 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003859
Mingming Yin3a941d42016-02-17 18:08:05 -08003860 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003861 if(config->offload_info.format == 0)
3862 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003863 if (config->offload_info.sample_rate == 0)
3864 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003865 }
3866
Mingming Yin90310102013-11-13 16:57:00 -08003867 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303868 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003869 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003870 ret = -EINVAL;
3871 goto error_open;
3872 }
3873
3874 out->compr_config.codec = (struct snd_codec *)
3875 calloc(1, sizeof(struct snd_codec));
3876
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003877 if (!out->compr_config.codec) {
3878 ret = -ENOMEM;
3879 goto error_open;
3880 }
3881
vivek mehta0ea887a2015-08-26 14:01:20 -07003882 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303883 out->stream.pause = out_pause;
3884 out->stream.flush = out_flush;
3885 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003886 out->usecase = get_offload_usecase(adev, true);
3887 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003888 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003889 out->stream.set_callback = out_set_callback;
3890 out->stream.pause = out_pause;
3891 out->stream.resume = out_resume;
3892 out->stream.drain = out_drain;
3893 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003894 out->usecase = get_offload_usecase(adev, false);
3895 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003896 }
vivek mehta446c3962015-09-14 10:57:35 -07003897
3898 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003899 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3900 config->format == 0 && config->sample_rate == 0 &&
3901 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003902 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003903 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3904 } else {
3905 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3906 ret = -EEXIST;
3907 goto error_open;
3908 }
vivek mehta446c3962015-09-14 10:57:35 -07003909 }
3910
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003911 if (config->offload_info.channel_mask)
3912 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003913 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003914 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003915 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003916 } else {
3917 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3918 ret = -EINVAL;
3919 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003920 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003921
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003922 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003923 out->sample_rate = config->offload_info.sample_rate;
3924
Mingming Yin3ee55c62014-08-04 14:23:35 -07003925 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003926
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303927 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3928 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3929 audio_extn_dolby_send_ddp_endp_params(adev);
3930 audio_extn_dolby_set_dmid(adev);
3931 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003933 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003934 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003935 out->compr_config.codec->bit_rate =
3936 config->offload_info.bit_rate;
3937 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303938 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303940 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003941 /*TODO: Do we need to change it for passthrough */
3942 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003943
Manish Dewangana6fc5442015-08-24 20:30:31 +05303944 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3945 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3946 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3947 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303948
3949 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3950 AUDIO_FORMAT_PCM) {
3951
3952 /*Based on platform support, configure appropriate alsa format for corresponding
3953 *hal input format.
3954 */
3955 out->compr_config.codec->format = hal_format_to_alsa(
3956 config->offload_info.format);
3957
Ashish Jain83a6cc22016-06-28 14:34:17 +05303958 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303959 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303960 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303961
3962 /*for direct PCM playback populate bit_width based on selected alsa format as
3963 *hal input format and alsa format might differ based on platform support.
3964 */
3965 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303966 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303967
3968 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3969
3970 /* Check if alsa session is configured with the same format as HAL input format,
3971 * if not then derive correct fragment size needed to accomodate the
3972 * conversion of HAL input format to alsa format.
3973 */
3974 audio_extn_utils_update_direct_pcm_fragment_size(out);
3975
3976 /*if hal input and output fragment size is different this indicates HAL input format is
3977 *not same as the alsa format
3978 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303979 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303980 /*Allocate a buffer to convert input data to the alsa configured format.
3981 *size of convert buffer is equal to the size required to hold one fragment size
3982 *worth of pcm data, this is because flinger does not write more than fragment_size
3983 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303984 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3985 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303986 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3987 ret = -ENOMEM;
3988 goto error_open;
3989 }
3990 }
3991 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3992 out->compr_config.fragment_size =
3993 audio_extn_passthru_get_buffer_size(&config->offload_info);
3994 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3995 } else {
3996 out->compr_config.fragment_size =
3997 platform_get_compress_offload_buffer_size(&config->offload_info);
3998 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3999 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004000
Amit Shekhar6f461b12014-08-01 14:52:58 -07004001 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304002 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004003
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004004 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4005 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004006
Alexy Josephaa54c872014-12-03 02:46:47 -08004007
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004008 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304009 out->send_next_track_params = false;
4010 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004011 out->offload_state = OFFLOAD_STATE_IDLE;
4012 out->playback_started = 0;
4013
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004014 audio_extn_dts_create_state_notifier_node(out->usecase);
4015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004016 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4017 __func__, config->offload_info.version,
4018 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304019
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304020 /* Check if DSD audio format is supported in codec
4021 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304022 */
4023
4024 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304025 (!platform_check_codec_dsd_support(adev->platform) ||
4026 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304027 ret = -EINVAL;
4028 goto error_open;
4029 }
4030
Ashish Jain5106d362016-05-11 19:23:33 +05304031 /* Disable gapless if any of the following is true
4032 * passthrough playback
4033 * AV playback
4034 * Direct PCM playback
4035 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304036 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304037 (config->format == AUDIO_FORMAT_DSD) ||
4038 config->offload_info.has_video ||
4039 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304040 check_and_set_gapless_mode(adev, false);
4041 } else
4042 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004043
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304044 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004045 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4046 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304047 if (config->format == AUDIO_FORMAT_DSD) {
4048 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4049 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4050 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004051
4052 create_offload_callback_thread(out);
4053
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004054 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304055 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004056 if (ret != 0) {
4057 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4058 __func__, ret);
4059 goto error_open;
4060 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004061 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4062 if (config->sample_rate == 0)
4063 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4064 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4065 config->sample_rate != 8000) {
4066 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4067 ret = -EINVAL;
4068 goto error_open;
4069 }
4070 out->sample_rate = config->sample_rate;
4071 out->config.rate = config->sample_rate;
4072 if (config->format == AUDIO_FORMAT_DEFAULT)
4073 config->format = AUDIO_FORMAT_PCM_16_BIT;
4074 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4075 config->format = AUDIO_FORMAT_PCM_16_BIT;
4076 ret = -EINVAL;
4077 goto error_open;
4078 }
4079 out->format = config->format;
4080 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4081 out->config = pcm_config_afe_proxy_playback;
4082 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004083 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304084 unsigned int channels = 0;
4085 /*Update config params to default if not set by the caller*/
4086 if (config->sample_rate == 0)
4087 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4088 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4089 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4090 if (config->format == AUDIO_FORMAT_DEFAULT)
4091 config->format = AUDIO_FORMAT_PCM_16_BIT;
4092
4093 channels = audio_channel_count_from_out_mask(out->channel_mask);
4094
Ashish Jain83a6cc22016-06-28 14:34:17 +05304095 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4096 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004097 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4098 out->flags);
4099 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304100 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4101 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4102 out->config = pcm_config_low_latency;
4103 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4104 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4105 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304106 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4107 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4108 if (out->config.period_size <= 0) {
4109 ALOGE("Invalid configuration period size is not valid");
4110 ret = -EINVAL;
4111 goto error_open;
4112 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304113 } else {
4114 /* primary path is the default path selected if no other outputs are available/suitable */
4115 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4116 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4117 }
4118 out->hal_ip_format = format = out->format;
4119 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4120 out->hal_op_format = pcm_format_to_hal(out->config.format);
4121 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4122 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004123 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304124 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304125 if (out->hal_ip_format != out->hal_op_format) {
4126 uint32_t buffer_size = out->config.period_size *
4127 format_to_bitwidth_table[out->hal_op_format] *
4128 out->config.channels;
4129 out->convert_buffer = calloc(1, buffer_size);
4130 if (out->convert_buffer == NULL){
4131 ALOGE("Allocation failed for convert buffer for size %d",
4132 out->compr_config.fragment_size);
4133 ret = -ENOMEM;
4134 goto error_open;
4135 }
4136 ALOGD("Convert buffer allocated of size %d", buffer_size);
4137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 }
4139
Ashish Jain83a6cc22016-06-28 14:34:17 +05304140 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4141 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4142
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004143 /* TODO remove this hardcoding and check why width is zero*/
4144 if (out->bit_width == 0)
4145 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304146 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004147 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004148 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304149 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304150 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004151 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4152 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4153 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004154 if(adev->primary_output == NULL)
4155 adev->primary_output = out;
4156 else {
4157 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004158 ret = -EEXIST;
4159 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004160 }
4161 }
4162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 /* Check if this usecase is already existing */
4164 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004165 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4166 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004169 ret = -EEXIST;
4170 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 }
4172 pthread_mutex_unlock(&adev->lock);
4173
4174 out->stream.common.get_sample_rate = out_get_sample_rate;
4175 out->stream.common.set_sample_rate = out_set_sample_rate;
4176 out->stream.common.get_buffer_size = out_get_buffer_size;
4177 out->stream.common.get_channels = out_get_channels;
4178 out->stream.common.get_format = out_get_format;
4179 out->stream.common.set_format = out_set_format;
4180 out->stream.common.standby = out_standby;
4181 out->stream.common.dump = out_dump;
4182 out->stream.common.set_parameters = out_set_parameters;
4183 out->stream.common.get_parameters = out_get_parameters;
4184 out->stream.common.add_audio_effect = out_add_audio_effect;
4185 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4186 out->stream.get_latency = out_get_latency;
4187 out->stream.set_volume = out_set_volume;
4188 out->stream.write = out_write;
4189 out->stream.get_render_position = out_get_render_position;
4190 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004191 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004193 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004195 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004196 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197
4198 config->format = out->stream.common.get_format(&out->stream.common);
4199 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4200 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4201
4202 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304203 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004204 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004205
4206 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4207 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4208 popcount(out->channel_mask), out->playback_started);
4209
Eric Laurent994a6932013-07-17 11:51:42 -07004210 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004212
4213error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304214 if (out->convert_buffer)
4215 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004216 free(out);
4217 *stream_out = NULL;
4218 ALOGD("%s: exit: ret %d", __func__, ret);
4219 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220}
4221
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304222void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 struct audio_stream_out *stream)
4224{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004225 struct stream_out *out = (struct stream_out *)stream;
4226 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004227 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004228
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304229 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4230
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004231 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304232 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004233 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304234 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004235 if(ret != 0)
4236 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4237 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004238 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004239 out_standby(&stream->common);
4240
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004241 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004242 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004243 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004244 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004245 if (out->compr_config.codec != NULL)
4246 free(out->compr_config.codec);
4247 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004248
Ashish Jain83a6cc22016-06-28 14:34:17 +05304249 if (out->convert_buffer != NULL) {
4250 free(out->convert_buffer);
4251 out->convert_buffer = NULL;
4252 }
4253
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004254 if (adev->voice_tx_output == out)
4255 adev->voice_tx_output = NULL;
4256
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004257 pthread_cond_destroy(&out->cond);
4258 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004260 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261}
4262
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004263static void close_compress_sessions(struct audio_device *adev)
4264{
Mingming Yin7b762e72015-03-04 13:47:32 -08004265 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304266 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004267 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004268 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304269
4270 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004271 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304272 if (is_offload_usecase(usecase->id)) {
4273 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004274 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4275 out = usecase->stream.out;
4276 pthread_mutex_unlock(&adev->lock);
4277 out_standby(&out->stream.common);
4278 pthread_mutex_lock(&adev->lock);
4279 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304280 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004281 }
4282 pthread_mutex_unlock(&adev->lock);
4283}
4284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4286{
4287 struct audio_device *adev = (struct audio_device *)dev;
4288 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004290 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004291 int ret;
4292 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004294 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304297 if (!parms)
4298 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004299 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4300 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304301 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304302 if (strstr(snd_card_status, "OFFLINE")) {
4303 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304304 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004305 //close compress sessions on OFFLINE status
4306 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304307 } else if (strstr(snd_card_status, "ONLINE")) {
4308 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304309 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004310 //send dts hpx license if enabled
4311 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304312 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304313 }
4314
4315 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004316 status = voice_set_parameters(adev, parms);
4317 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004318 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004320 status = platform_set_parameters(adev->platform, parms);
4321 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004322 goto done;
4323
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004324 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4325 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004326 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4328 adev->bluetooth_nrec = true;
4329 else
4330 adev->bluetooth_nrec = false;
4331 }
4332
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004333 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4334 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4336 adev->screen_off = false;
4337 else
4338 adev->screen_off = true;
4339 }
4340
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004341 ret = str_parms_get_int(parms, "rotation", &val);
4342 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004343 bool reverse_speakers = false;
4344 switch(val) {
4345 // FIXME: note that the code below assumes that the speakers are in the correct placement
4346 // relative to the user when the device is rotated 90deg from its default rotation. This
4347 // assumption is device-specific, not platform-specific like this code.
4348 case 270:
4349 reverse_speakers = true;
4350 break;
4351 case 0:
4352 case 90:
4353 case 180:
4354 break;
4355 default:
4356 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004357 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004358 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004359 if (status == 0) {
4360 if (adev->speaker_lr_swap != reverse_speakers) {
4361 adev->speaker_lr_swap = reverse_speakers;
4362 // only update the selected device if there is active pcm playback
4363 struct audio_usecase *usecase;
4364 struct listnode *node;
4365 list_for_each(node, &adev->usecase_list) {
4366 usecase = node_to_item(node, struct audio_usecase, list);
4367 if (usecase->type == PCM_PLAYBACK) {
4368 select_devices(adev, usecase->id);
4369 break;
4370 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004371 }
4372 }
4373 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004374 }
4375
Mingming Yin514a8bc2014-07-29 15:22:21 -07004376 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4377 if (ret >= 0) {
4378 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4379 adev->bt_wb_speech_enabled = true;
4380 else
4381 adev->bt_wb_speech_enabled = false;
4382 }
4383
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004384 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4385 if (ret >= 0) {
4386 val = atoi(value);
4387 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004388 ALOGV("cache new ext disp type and edid");
4389 ret = platform_get_ext_disp_type(adev->platform);
4390 if (ret < 0) {
4391 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004392 status = ret;
4393 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004394 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004395 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004396 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004397 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004398 /*
4399 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4400 * Per AudioPolicyManager, USB device is higher priority than WFD.
4401 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4402 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4403 * starting voice call on USB
4404 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004405 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4406 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004407 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4408 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004409 }
vivek mehta344576a2016-04-12 18:56:03 -07004410 ALOGV("detected USB connect .. disable proxy");
4411 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004412 }
4413 }
4414
4415 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4416 if (ret >= 0) {
4417 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004418 /*
4419 * The HDMI / Displayport disconnect handling has been moved to
4420 * audio extension to ensure that its parameters are not
4421 * invalidated prior to updating sysfs of the disconnect event
4422 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4423 */
4424 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004425 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004426 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4427 if (ret >= 0) {
4428 audio_extn_usb_remove_device(val, atoi(value));
4429 }
vivek mehta344576a2016-04-12 18:56:03 -07004430 ALOGV("detected USB disconnect .. enable proxy");
4431 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004432 }
4433 }
4434
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304435 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4436 if (ret >= 0) {
4437 struct audio_usecase *usecase;
4438 struct listnode *node;
4439 list_for_each(node, &adev->usecase_list) {
4440 usecase = node_to_item(node, struct audio_usecase, list);
4441 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004442 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304443 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304444 lock_output_stream(usecase->stream.out);
4445 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304446 //force device switch to re configure encoder
4447 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304448 audio_extn_a2dp_set_handoff_mode(false);
4449 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304450 break;
4451 }
4452 }
4453 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304454 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004455done:
4456 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004457 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304458error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004459 ALOGV("%s: exit with code(%d)", __func__, status);
4460 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461}
4462
4463static char* adev_get_parameters(const struct audio_hw_device *dev,
4464 const char *keys)
4465{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004466 struct audio_device *adev = (struct audio_device *)dev;
4467 struct str_parms *reply = str_parms_create();
4468 struct str_parms *query = str_parms_create_str(keys);
4469 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304470 char value[256] = {0};
4471 int ret = 0;
4472
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004473 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004474 if (reply) {
4475 str_parms_destroy(reply);
4476 }
4477 if (query) {
4478 str_parms_destroy(query);
4479 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004480 ALOGE("adev_get_parameters: failed to create query or reply");
4481 return NULL;
4482 }
4483
Naresh Tannirud7205b62014-06-20 02:54:48 +05304484 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4485 sizeof(value));
4486 if (ret >=0) {
4487 int val = 1;
4488 pthread_mutex_lock(&adev->snd_card_status.lock);
4489 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4490 val = 0;
4491 pthread_mutex_unlock(&adev->snd_card_status.lock);
4492 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4493 goto exit;
4494 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004495
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004496 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004497 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004498 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004499 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304500 pthread_mutex_unlock(&adev->lock);
4501
Naresh Tannirud7205b62014-06-20 02:54:48 +05304502exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004503 str = str_parms_to_str(reply);
4504 str_parms_destroy(query);
4505 str_parms_destroy(reply);
4506
4507 ALOGV("%s: exit: returns - %s", __func__, str);
4508 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509}
4510
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004511static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512{
4513 return 0;
4514}
4515
4516static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4517{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004518 int ret;
4519 struct audio_device *adev = (struct audio_device *)dev;
4520 pthread_mutex_lock(&adev->lock);
4521 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004522 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004523 pthread_mutex_unlock(&adev->lock);
4524 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525}
4526
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004527static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4528 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529{
4530 return -ENOSYS;
4531}
4532
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004533static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4534 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535{
4536 return -ENOSYS;
4537}
4538
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004539static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4540 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541{
4542 return -ENOSYS;
4543}
4544
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004545static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4546 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004547{
4548 return -ENOSYS;
4549}
4550
4551static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4552{
4553 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 pthread_mutex_lock(&adev->lock);
4556 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004557 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004559 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004560 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004561 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004562 adev->current_call_output = NULL;
4563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 }
4565 pthread_mutex_unlock(&adev->lock);
4566 return 0;
4567}
4568
4569static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4570{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004571 int ret;
4572
4573 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004574 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004575 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4576 pthread_mutex_unlock(&adev->lock);
4577
4578 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579}
4580
4581static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4582{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004583 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004584 return 0;
4585}
4586
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004587static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 const struct audio_config *config)
4589{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004590 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004592 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4593 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594}
4595
4596static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004597 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 audio_devices_t devices,
4599 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004600 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304601 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004602 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004603 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604{
4605 struct audio_device *adev = (struct audio_device *)dev;
4606 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004607 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004608 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004609 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304610 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304613 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4614 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304616 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617
4618 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004619
4620 if (!in) {
4621 ALOGE("failed to allocate input stream");
4622 return -ENOMEM;
4623 }
4624
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304625 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304626 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4627 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004628 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004629 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 in->stream.common.get_sample_rate = in_get_sample_rate;
4632 in->stream.common.set_sample_rate = in_set_sample_rate;
4633 in->stream.common.get_buffer_size = in_get_buffer_size;
4634 in->stream.common.get_channels = in_get_channels;
4635 in->stream.common.get_format = in_get_format;
4636 in->stream.common.set_format = in_set_format;
4637 in->stream.common.standby = in_standby;
4638 in->stream.common.dump = in_dump;
4639 in->stream.common.set_parameters = in_set_parameters;
4640 in->stream.common.get_parameters = in_get_parameters;
4641 in->stream.common.add_audio_effect = in_add_audio_effect;
4642 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4643 in->stream.set_gain = in_set_gain;
4644 in->stream.read = in_read;
4645 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4646
4647 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004648 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 in->standby = 1;
4651 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004652 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004653 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004655 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004656 if (in->realtime) {
4657 in->config = pcm_config_audio_capture_rt;
4658 in->sample_rate = in->config.rate;
4659 in->af_period_multiplier = af_period_multiplier;
4660 } else {
4661 in->config = pcm_config_audio_capture;
4662 in->config.rate = config->sample_rate;
4663 in->sample_rate = config->sample_rate;
4664 in->af_period_multiplier = 1;
4665 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304666 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304668 /* restrict 24 bit capture for unprocessed source only
4669 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4670 */
4671 if (config->format == AUDIO_FORMAT_DEFAULT) {
4672 config->format = AUDIO_FORMAT_PCM_16_BIT;
4673 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4674 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4675 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4676 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4677 bool ret_error = false;
4678 in->bit_width = 24;
4679 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4680 from HAL is 24_packed and 8_24
4681 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4682 24_packed return error indicating supported format is 24_packed
4683 *> In case of any other source requesting 24 bit or float return error
4684 indicating format supported is 16 bit only.
4685
4686 on error flinger will retry with supported format passed
4687 */
4688 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4689 (source != AUDIO_SOURCE_CAMCORDER)) {
4690 config->format = AUDIO_FORMAT_PCM_16_BIT;
4691 if (config->sample_rate > 48000)
4692 config->sample_rate = 48000;
4693 ret_error = true;
4694 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4695 in->config.format = PCM_FORMAT_S24_3LE;
4696 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4697 in->config.format = PCM_FORMAT_S24_LE;
4698 } else {
4699 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4700 ret_error = true;
4701 }
4702
4703 if (ret_error) {
4704 ret = -EINVAL;
4705 goto err_open;
4706 }
4707 }
4708
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304709 in->usecase = USECASE_AUDIO_RECORD;
4710 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4711 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4712 is_low_latency = true;
4713#if LOW_LATENCY_CAPTURE_USE_CASE
4714 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4715#endif
4716 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4717 }
4718
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304719 pthread_mutex_lock(&adev->lock);
4720 if (in->usecase == USECASE_AUDIO_RECORD) {
4721 if (!(adev->pcm_record_uc_state) &&
4722 ((flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0)) {
4723 ALOGV("%s: pcm record usecase", __func__);
4724 adev->pcm_record_uc_state = 1;
4725 } else {
4726 /*
4727 * Assign default compress record use case, actual use case
4728 * assignment will happen later.
4729 */
4730 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
4731 ALOGV("%s: compress record usecase", __func__);
4732 }
4733 }
4734 pthread_mutex_unlock(&adev->lock);
4735
4736 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304737 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4738 (adev->mode != AUDIO_MODE_IN_CALL)) {
4739 ret = -EINVAL;
4740 goto err_open;
4741 }
4742
4743 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4744 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004745 if (config->sample_rate == 0)
4746 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4747 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4748 config->sample_rate != 8000) {
4749 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4750 ret = -EINVAL;
4751 goto err_open;
4752 }
4753 if (config->format == AUDIO_FORMAT_DEFAULT)
4754 config->format = AUDIO_FORMAT_PCM_16_BIT;
4755 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4756 config->format = AUDIO_FORMAT_PCM_16_BIT;
4757 ret = -EINVAL;
4758 goto err_open;
4759 }
4760
4761 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4762 in->config = pcm_config_afe_proxy_record;
4763 in->config.channels = channel_count;
4764 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304765 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304766 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4767 in, config, &channel_mask_updated)) {
4768 if (channel_mask_updated == true) {
4769 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4770 __func__, config->channel_mask);
4771 ret = -EINVAL;
4772 goto err_open;
4773 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304774 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004775 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004776 audio_extn_compr_cap_format_supported(config->format) &&
4777 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004778 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304779 } else if (audio_extn_cin_applicable_stream(in)) {
4780 ret = audio_extn_cin_configure_input_stream(in);
4781 if (ret)
4782 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004783 } else {
4784 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004785 if (!in->realtime) {
4786 in->format = config->format;
4787 frame_size = audio_stream_in_frame_size(&in->stream);
4788 buffer_size = get_input_buffer_size(config->sample_rate,
4789 config->format,
4790 channel_count,
4791 is_low_latency);
4792 in->config.period_size = buffer_size / frame_size;
4793 }
4794
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004795 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4796 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4797 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004798 (in->config.rate == 8000 || in->config.rate == 16000 ||
4799 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004800 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4801 voice_extn_compress_voip_open_input_stream(in);
4802 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304805 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4806 &adev->streams_input_cfg_list,
4807 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304808 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304809
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004810 /* This stream could be for sound trigger lab,
4811 get sound trigger pcm if present */
4812 audio_extn_sound_trigger_check_and_get_session(in);
4813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004815 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004816 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817
4818err_open:
4819 free(in);
4820 *stream_in = NULL;
4821 return ret;
4822}
4823
4824static void adev_close_input_stream(struct audio_hw_device *dev,
4825 struct audio_stream_in *stream)
4826{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004827 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004828 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004829 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304830
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304831 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004832
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304833 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004834 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304835
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004836 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304837 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004838 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304839 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004840 if (ret != 0)
4841 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4842 __func__, ret);
4843 } else
4844 in_standby(&stream->common);
4845
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004846 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004847 audio_extn_ssr_deinit();
4848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304850 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004851 audio_extn_compr_cap_format_supported(in->config.format))
4852 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304853
4854 if (in->usecase == USECASE_AUDIO_RECORD) {
4855 pthread_mutex_lock(&adev->lock);
4856 adev->pcm_record_uc_state = 0;
4857 pthread_mutex_unlock(&adev->lock);
4858 }
4859
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304860 if (audio_extn_cin_attached_usecase(in->usecase))
4861 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004862
Mingming Yinfd7607b2016-01-22 12:48:44 -08004863 if (in->is_st_session) {
4864 ALOGV("%s: sound trigger pcm stop lab", __func__);
4865 audio_extn_sound_trigger_stop_lab(in);
4866 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004867 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868 return;
4869}
4870
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004871static int adev_dump(const audio_hw_device_t *device __unused,
4872 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873{
4874 return 0;
4875}
4876
4877static int adev_close(hw_device_t *device)
4878{
4879 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004880
4881 if (!adev)
4882 return 0;
4883
4884 pthread_mutex_lock(&adev_init_lock);
4885
4886 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004887 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004888 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304889 audio_extn_utils_release_streams_cfg_lists(
4890 &adev->streams_output_cfg_list,
4891 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304892 if (audio_extn_qaf_is_enabled())
4893 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004894 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004895 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004896 free(adev->snd_dev_ref_cnt);
4897 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004898 if (adev->adm_deinit)
4899 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304900 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004901 free(device);
4902 adev = NULL;
4903 }
4904 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906 return 0;
4907}
4908
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004909/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4910 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4911 * just that it _might_ work.
4912 */
4913static int period_size_is_plausible_for_low_latency(int period_size)
4914{
4915 switch (period_size) {
4916 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004917 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004918 case 240:
4919 case 320:
4920 case 480:
4921 return 1;
4922 default:
4923 return 0;
4924 }
4925}
4926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927static int adev_open(const hw_module_t *module, const char *name,
4928 hw_device_t **device)
4929{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304930 int ret;
4931
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004932 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004933 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4934
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004935 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004936 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004937 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004938 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004939 ALOGD("%s: returning existing instance of adev", __func__);
4940 ALOGD("%s: exit", __func__);
4941 pthread_mutex_unlock(&adev_init_lock);
4942 return 0;
4943 }
4944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945 adev = calloc(1, sizeof(struct audio_device));
4946
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004947 if (!adev) {
4948 pthread_mutex_unlock(&adev_init_lock);
4949 return -ENOMEM;
4950 }
4951
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004952 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004954 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4955 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4956 adev->device.common.module = (struct hw_module_t *)module;
4957 adev->device.common.close = adev_close;
4958
4959 adev->device.init_check = adev_init_check;
4960 adev->device.set_voice_volume = adev_set_voice_volume;
4961 adev->device.set_master_volume = adev_set_master_volume;
4962 adev->device.get_master_volume = adev_get_master_volume;
4963 adev->device.set_master_mute = adev_set_master_mute;
4964 adev->device.get_master_mute = adev_get_master_mute;
4965 adev->device.set_mode = adev_set_mode;
4966 adev->device.set_mic_mute = adev_set_mic_mute;
4967 adev->device.get_mic_mute = adev_get_mic_mute;
4968 adev->device.set_parameters = adev_set_parameters;
4969 adev->device.get_parameters = adev_get_parameters;
4970 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4971 adev->device.open_output_stream = adev_open_output_stream;
4972 adev->device.close_output_stream = adev_close_output_stream;
4973 adev->device.open_input_stream = adev_open_input_stream;
4974 adev->device.close_input_stream = adev_close_input_stream;
4975 adev->device.dump = adev_dump;
4976
4977 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004979 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004980 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004983 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004984 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004985 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004986 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004987 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004988 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004989 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004990 adev->offload_usecases_state = 0;
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304991 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304992 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304993 adev->perf_lock_opts[0] = 0x101;
4994 adev->perf_lock_opts[1] = 0x20E;
4995 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304996
4997 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4998 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004999 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005000 adev->platform = platform_init(adev);
5001 if (!adev->platform) {
5002 free(adev->snd_dev_ref_cnt);
5003 free(adev);
5004 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5005 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005006 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305007 pthread_mutex_destroy(&adev->lock);
5008 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005009 return -EINVAL;
5010 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005011
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305012 if (audio_extn_qaf_is_enabled()) {
5013 ret = audio_extn_qaf_init(adev);
5014 if (ret < 0) {
5015 free(adev);
5016 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5017 *device = NULL;
5018 pthread_mutex_unlock(&adev_init_lock);
5019 pthread_mutex_destroy(&adev->lock);
5020 return ret;
5021 }
5022
5023 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5024 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5025 }
5026
Naresh Tanniru4c630392014-05-12 01:05:52 +05305027 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5028
Eric Laurentc4aef752013-09-12 17:45:53 -07005029 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5030 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5031 if (adev->visualizer_lib == NULL) {
5032 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5033 } else {
5034 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5035 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005036 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005037 "visualizer_hal_start_output");
5038 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005039 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005040 "visualizer_hal_stop_output");
5041 }
5042 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305043 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005044 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005045 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005046 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005047
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005048 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5049 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5050 if (adev->offload_effects_lib == NULL) {
5051 ALOGE("%s: DLOPEN failed for %s", __func__,
5052 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5053 } else {
5054 ALOGV("%s: DLOPEN successful for %s", __func__,
5055 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5056 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305057 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005058 "offload_effects_bundle_hal_start_output");
5059 adev->offload_effects_stop_output =
5060 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5061 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005062 adev->offload_effects_set_hpx_state =
5063 (int (*)(bool))dlsym(adev->offload_effects_lib,
5064 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305065 adev->offload_effects_get_parameters =
5066 (void (*)(struct str_parms *, struct str_parms *))
5067 dlsym(adev->offload_effects_lib,
5068 "offload_effects_bundle_get_parameters");
5069 adev->offload_effects_set_parameters =
5070 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5071 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005072 }
5073 }
5074
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005075 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5076 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5077 if (adev->adm_lib == NULL) {
5078 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5079 } else {
5080 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5081 adev->adm_init = (adm_init_t)
5082 dlsym(adev->adm_lib, "adm_init");
5083 adev->adm_deinit = (adm_deinit_t)
5084 dlsym(adev->adm_lib, "adm_deinit");
5085 adev->adm_register_input_stream = (adm_register_input_stream_t)
5086 dlsym(adev->adm_lib, "adm_register_input_stream");
5087 adev->adm_register_output_stream = (adm_register_output_stream_t)
5088 dlsym(adev->adm_lib, "adm_register_output_stream");
5089 adev->adm_deregister_stream = (adm_deregister_stream_t)
5090 dlsym(adev->adm_lib, "adm_deregister_stream");
5091 adev->adm_request_focus = (adm_request_focus_t)
5092 dlsym(adev->adm_lib, "adm_request_focus");
5093 adev->adm_abandon_focus = (adm_abandon_focus_t)
5094 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005095 adev->adm_set_config = (adm_set_config_t)
5096 dlsym(adev->adm_lib, "adm_set_config");
5097 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5098 dlsym(adev->adm_lib, "adm_request_focus_v2");
5099 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5100 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5101 adev->adm_on_routing_change = (adm_on_routing_change_t)
5102 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005103 }
5104 }
5105
Mingming Yin514a8bc2014-07-29 15:22:21 -07005106 adev->bt_wb_speech_enabled = false;
5107
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005108 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005109 *device = &adev->device.common;
5110
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305111 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5112 &adev->streams_output_cfg_list,
5113 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005114
Kiran Kandi910e1862013-10-29 13:29:42 -07005115 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005116
5117 char value[PROPERTY_VALUE_MAX];
5118 int trial;
5119 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5120 trial = atoi(value);
5121 if (period_size_is_plausible_for_low_latency(trial)) {
5122 pcm_config_low_latency.period_size = trial;
5123 pcm_config_low_latency.start_threshold = trial / 4;
5124 pcm_config_low_latency.avail_min = trial / 4;
5125 configured_low_latency_capture_period_size = trial;
5126 }
5127 }
5128 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5129 trial = atoi(value);
5130 if (period_size_is_plausible_for_low_latency(trial)) {
5131 configured_low_latency_capture_period_size = trial;
5132 }
5133 }
5134
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005135 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5136 af_period_multiplier = atoi(value);
5137 if (af_period_multiplier < 0)
5138 af_period_multiplier = 2;
5139 else if (af_period_multiplier > 4)
5140 af_period_multiplier = 4;
5141
5142 ALOGV("new period_multiplier = %d", af_period_multiplier);
5143 }
5144
vivek mehta446c3962015-09-14 10:57:35 -07005145 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005146 pthread_mutex_unlock(&adev_init_lock);
5147
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005148 if (adev->adm_init)
5149 adev->adm_data = adev->adm_init();
5150
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305151 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305152 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005153 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005154 return 0;
5155}
5156
5157static struct hw_module_methods_t hal_module_methods = {
5158 .open = adev_open,
5159};
5160
5161struct audio_module HAL_MODULE_INFO_SYM = {
5162 .common = {
5163 .tag = HARDWARE_MODULE_TAG,
5164 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5165 .hal_api_version = HARDWARE_HAL_API_VERSION,
5166 .id = AUDIO_HARDWARE_MODULE_ID,
5167 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005168 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169 .methods = &hal_module_methods,
5170 },
5171};