blob: 8c37bae4f15b4aa845865b7f0f0ac8fc47817da7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
524 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800525 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526
527 return false;
528}
529
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700530static inline bool is_mmap_usecase(audio_usecase_t uc_id)
531{
532 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
533 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
534}
535
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530536int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530537{
538 int snd_scard_state;
539
540 if (!adev)
541 return SND_CARD_STATE_OFFLINE;
542
543 pthread_mutex_lock(&adev->snd_card_status.lock);
544 snd_scard_state = adev->snd_card_status.state;
545 pthread_mutex_unlock(&adev->snd_card_status.lock);
546
547 return snd_scard_state;
548}
549
550static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
551{
552 if (!adev)
553 return -ENOSYS;
554
555 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700556 if (adev->snd_card_status.state != snd_scard_state) {
557 adev->snd_card_status.state = snd_scard_state;
558 platform_snd_card_update(adev->platform, snd_scard_state);
559 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530560 pthread_mutex_unlock(&adev->snd_card_status.lock);
561
562 return 0;
563}
564
Avinash Vaish71a8b972014-07-24 15:36:33 +0530565static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
566 struct audio_usecase *uc_info)
567{
568 struct listnode *node;
569 struct audio_usecase *usecase;
570
571 if (uc_info == NULL)
572 return -EINVAL;
573
574 /* Re-route all voice usecases on the shared backend other than the
575 specified usecase to new snd devices */
576 list_for_each(node, &adev->usecase_list) {
577 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800578 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530579 enable_audio_route(adev, usecase);
580 }
581 return 0;
582}
583
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530584static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530585{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530586 ALOGV("%s", __func__);
587 audio_route_apply_and_update_path(adev->audio_route,
588 "asrc-mode");
589 adev->asrc_mode_enabled = true;
590}
591
592static void disable_asrc_mode(struct audio_device *adev)
593{
594 ALOGV("%s", __func__);
595 audio_route_reset_and_update_path(adev->audio_route,
596 "asrc-mode");
597 adev->asrc_mode_enabled = false;
598}
599
600/*
601 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
602 * 44.1 or Native DSD backends are enabled for any of current use case.
603 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
604 * - Disable current mix path use case(Headphone backend) and re-enable it with
605 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
606 * e.g. Naitve DSD or Headphone 44.1 -> + 48
607 */
608static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
609{
610 ALOGV("%s snd device %d", __func__, snd_device);
611 int new_backend_idx = platform_get_backend_index(snd_device);
612
613 if (((new_backend_idx == HEADPHONE_BACKEND) ||
614 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
615 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
616 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530617 struct listnode *node = NULL;
618 struct audio_usecase *uc = NULL;
619 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530620 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530621
622 list_for_each(node, &adev->usecase_list) {
623 uc = node_to_item(node, struct audio_usecase, list);
624 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530625 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530626 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
627
628 if((new_backend_idx == HEADPHONE_BACKEND) &&
629 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
630 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530631 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
632 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530633 enable_asrc_mode(adev);
634 break;
635 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
636 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
637 (usecase_backend_idx == HEADPHONE_BACKEND)) {
638 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
639 __func__);
640 disable_audio_route(adev, uc);
641 disable_snd_device(adev, uc->out_snd_device);
642 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
643 if (new_backend_idx == DSD_NATIVE_BACKEND)
644 audio_route_apply_and_update_path(adev->audio_route,
645 "hph-true-highquality-mode");
646 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
647 (curr_out->bit_width >= 24))
648 audio_route_apply_and_update_path(adev->audio_route,
649 "hph-highquality-mode");
650 enable_asrc_mode(adev);
651 enable_snd_device(adev, uc->out_snd_device);
652 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 break;
654 }
655 }
656 }
657 }
658}
659
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700660int pcm_ioctl(struct pcm *pcm, int request, ...)
661{
662 va_list ap;
663 void * arg;
664 int pcm_fd = *(int*)pcm;
665
666 va_start(ap, request);
667 arg = va_arg(ap, void *);
668 va_end(ap);
669
670 return ioctl(pcm_fd, request, arg);
671}
672
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700673int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700674 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800675{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700677 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800678
679 if (usecase == NULL)
680 return -EINVAL;
681
682 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
683
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800684 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800686 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700687 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800688
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800689#ifdef DS1_DOLBY_DAP_ENABLED
690 audio_extn_dolby_set_dmid(adev);
691 audio_extn_dolby_set_endpoint(adev);
692#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700693 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700694 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530695 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700696 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530697 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800698 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700699 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700700 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700701 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800702 ALOGV("%s: exit", __func__);
703 return 0;
704}
705
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700706int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700707 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800708{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700710 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800711
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530712 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800713 return -EINVAL;
714
715 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 if (usecase->type == PCM_CAPTURE)
717 snd_device = usecase->in_snd_device;
718 else
719 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800720 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700721 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700722 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700723 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700724 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530725 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726 ALOGV("%s: exit", __func__);
727 return 0;
728}
729
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700730int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700731 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530733 int i, num_devices = 0;
734 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700735 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
736
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800737 if (snd_device < SND_DEVICE_MIN ||
738 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800739 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800740 return -EINVAL;
741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742
743 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700744
745 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
746 ALOGE("%s: Invalid sound device returned", __func__);
747 return -EINVAL;
748 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700750 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700751 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700752 return 0;
753 }
754
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530755
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700756 if (audio_extn_spkr_prot_is_enabled())
757 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700758
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800759 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
760 audio_extn_spkr_prot_is_enabled()) {
761 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700762 adev->snd_dev_ref_cnt[snd_device]--;
763 return -EINVAL;
764 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200765 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800766 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800767 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200768 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800769 return -EINVAL;
770 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700771 } else if (platform_split_snd_device(adev->platform,
772 snd_device,
773 &num_devices,
774 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530775 for (i = 0; i < num_devices; i++) {
776 enable_snd_device(adev, new_snd_devices[i]);
777 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800778 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700779 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530780
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530781 if (platform_check_codec_asrc_support(adev->platform))
782 check_and_set_asrc_mode(adev, snd_device);
783
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530784 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
785 (audio_extn_a2dp_start_playback() < 0)) {
786 ALOGE(" fail to configure A2dp control path ");
787 return -EINVAL;
788 }
789
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700790 /* due to the possibility of calibration overwrite between listen
791 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700792 audio_extn_sound_trigger_update_device_status(snd_device,
793 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530794 audio_extn_listen_update_device_status(snd_device,
795 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700796 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700797 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700798 audio_extn_sound_trigger_update_device_status(snd_device,
799 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530800 audio_extn_listen_update_device_status(snd_device,
801 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700802 return -EINVAL;
803 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300804 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700805 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530806
807 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
808 !adev->native_playback_enabled &&
809 audio_is_true_native_stream_active(adev)) {
810 ALOGD("%s: %d: napb: enabling native mode in hardware",
811 __func__, __LINE__);
812 audio_route_apply_and_update_path(adev->audio_route,
813 "true-native-mode");
814 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817 return 0;
818}
819
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700820int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700821 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800822{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530823 int i, num_devices = 0;
824 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700825 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
826
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800827 if (snd_device < SND_DEVICE_MIN ||
828 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800829 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800830 return -EINVAL;
831 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
833 ALOGE("%s: device ref cnt is already 0", __func__);
834 return -EINVAL;
835 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700836
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700838
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700839 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
840 ALOGE("%s: Invalid sound device returned", __func__);
841 return -EINVAL;
842 }
843
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700845 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530846
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800847 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
848 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700849 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700850 } else if (platform_split_snd_device(adev->platform,
851 snd_device,
852 &num_devices,
853 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530854 for (i = 0; i < num_devices; i++) {
855 disable_snd_device(adev, new_snd_devices[i]);
856 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300857 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700858 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300859 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700860
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530861 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
862 audio_extn_a2dp_stop_playback();
863
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700864 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530865 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530866 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
867 adev->native_playback_enabled) {
868 ALOGD("%s: %d: napb: disabling native mode in hardware",
869 __func__, __LINE__);
870 audio_route_reset_and_update_path(adev->audio_route,
871 "true-native-mode");
872 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530873 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
874 adev->asrc_mode_enabled) {
875 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530876 disable_asrc_mode(adev);
877 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530878 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530879
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200880 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700881 audio_extn_sound_trigger_update_device_status(snd_device,
882 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530883 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800884 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800887 return 0;
888}
889
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700890/*
891 legend:
892 uc - existing usecase
893 new_uc - new usecase
894 d1, d11, d2 - SND_DEVICE enums
895 a1, a2 - corresponding ANDROID device enums
896 B1, B2 - backend strings
897
898case 1
899 uc->dev d1 (a1) B1
900 new_uc->dev d1 (a1), d2 (a2) B1, B2
901
902 resolution: disable and enable uc->dev on d1
903
904case 2
905 uc->dev d1 (a1) B1
906 new_uc->dev d11 (a1) B1
907
908 resolution: need to switch uc since d1 and d11 are related
909 (e.g. speaker and voice-speaker)
910 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
911
912case 3
913 uc->dev d1 (a1) B1
914 new_uc->dev d2 (a2) B2
915
916 resolution: no need to switch uc
917
918case 4
919 uc->dev d1 (a1) B1
920 new_uc->dev d2 (a2) B1
921
922 resolution: disable enable uc-dev on d2 since backends match
923 we cannot enable two streams on two different devices if they
924 share the same backend. e.g. if offload is on speaker device using
925 QUAD_MI2S backend and a low-latency stream is started on voice-handset
926 using the same backend, offload must also be switched to voice-handset.
927
928case 5
929 uc->dev d1 (a1) B1
930 new_uc->dev d1 (a1), d2 (a2) B1
931
932 resolution: disable enable uc-dev on d2 since backends match
933 we cannot enable two streams on two different devices if they
934 share the same backend.
935
936case 6
937 uc->dev d1 (a1) B1
938 new_uc->dev d2 (a1) B2
939
940 resolution: no need to switch
941
942case 7
943 uc->dev d1 (a1), d2 (a2) B1, B2
944 new_uc->dev d1 (a1) B1
945
946 resolution: no need to switch
947
948*/
949static snd_device_t derive_playback_snd_device(void * platform,
950 struct audio_usecase *uc,
951 struct audio_usecase *new_uc,
952 snd_device_t new_snd_device)
953{
954 audio_devices_t a1 = uc->stream.out->devices;
955 audio_devices_t a2 = new_uc->stream.out->devices;
956
957 snd_device_t d1 = uc->out_snd_device;
958 snd_device_t d2 = new_snd_device;
959
960 // Treat as a special case when a1 and a2 are not disjoint
961 if ((a1 != a2) && (a1 & a2)) {
962 snd_device_t d3[2];
963 int num_devices = 0;
964 int ret = platform_split_snd_device(platform,
965 popcount(a1) > 1 ? d1 : d2,
966 &num_devices,
967 d3);
968 if (ret < 0) {
969 if (ret != -ENOSYS) {
970 ALOGW("%s failed to split snd_device %d",
971 __func__,
972 popcount(a1) > 1 ? d1 : d2);
973 }
974 goto end;
975 }
976
977 // NB: case 7 is hypothetical and isn't a practical usecase yet.
978 // But if it does happen, we need to give priority to d2 if
979 // the combo devices active on the existing usecase share a backend.
980 // This is because we cannot have a usecase active on a combo device
981 // and a new usecase requests one device in this combo pair.
982 if (platform_check_backends_match(d3[0], d3[1])) {
983 return d2; // case 5
984 } else {
985 return d1; // case 1
986 }
987 } else {
988 if (platform_check_backends_match(d1, d2)) {
989 return d2; // case 2, 4
990 } else {
991 return d1; // case 6, 3
992 }
993 }
994
995end:
996 return d2; // return whatever was calculated before.
997}
998
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301000 struct audio_usecase *uc_info,
1001 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001002{
1003 struct listnode *node;
1004 struct audio_usecase *usecase;
1005 bool switch_device[AUDIO_USECASE_MAX];
1006 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001007 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301008 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001009 /*
1010 * This function is to make sure that all the usecases that are active on
1011 * the hardware codec backend are always routed to any one device that is
1012 * handled by the hardware codec.
1013 * For example, if low-latency and deep-buffer usecases are currently active
1014 * on speaker and out_set_parameters(headset) is received on low-latency
1015 * output, then we have to make sure deep-buffer is also switched to headset,
1016 * because of the limitation that both the devices cannot be enabled
1017 * at the same time as they share the same backend.
1018 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001019 /*
1020 * This call is to check if we need to force routing for a particular stream
1021 * If there is a backend configuration change for the device when a
1022 * new stream starts, then ADM needs to be closed and re-opened with the new
1023 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001024 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001025 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001026 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1027 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301028 /* For a2dp device reconfigure all active sessions
1029 * with new AFE encoder format based on a2dp state
1030 */
1031 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1032 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1033 audio_extn_a2dp_is_force_device_switch()) {
1034 force_routing = true;
1035 force_restart_session = true;
1036 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301037 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1038
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001040 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001041 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1043 switch_device[i] = false;
1044
1045 list_for_each(node, &adev->usecase_list) {
1046 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001047
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301048 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1049 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301050 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301051 platform_get_snd_device_name(usecase->out_snd_device),
1052 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001053 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301054 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001055 (derive_playback_snd_device(adev->platform,
1056 usecase, uc_info,
1057 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301058 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1059 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301060 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301061 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1062 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1063 ((force_restart_session) ||
1064 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301065
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301066 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1067 __func__, use_case_table[usecase->id],
1068 platform_get_snd_device_name(usecase->out_snd_device));
1069 disable_audio_route(adev, usecase);
1070 switch_device[usecase->id] = true;
1071 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 }
1073 }
1074
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301075 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1076 num_uc_to_switch);
1077
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001079 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301081 /* Make sure the previous devices to be disabled first and then enable the
1082 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 list_for_each(node, &adev->usecase_list) {
1084 usecase = node_to_item(node, struct audio_usecase, list);
1085 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 }
1088 }
1089
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001090 list_for_each(node, &adev->usecase_list) {
1091 usecase = node_to_item(node, struct audio_usecase, list);
1092 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001093 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001094 }
1095 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097 /* Re-route all the usecases on the shared backend other than the
1098 specified usecase to new snd devices */
1099 list_for_each(node, &adev->usecase_list) {
1100 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301101 /* Update the out_snd_device only before enabling the audio route */
1102 if (switch_device[usecase->id]) {
1103 usecase->out_snd_device = snd_device;
1104 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301105 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301106 use_case_table[usecase->id],
1107 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001108 /* Update voc calibration before enabling VoIP route */
1109 if (usecase->type == VOIP_CALL)
1110 status = platform_switch_voice_call_device_post(adev->platform,
1111 usecase->out_snd_device,
1112 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301113 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301114 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 }
1116 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 }
1118}
1119
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301120static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001121 struct audio_usecase *uc_info,
1122 snd_device_t snd_device)
1123{
1124 struct listnode *node;
1125 struct audio_usecase *usecase;
1126 bool switch_device[AUDIO_USECASE_MAX];
1127 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301128 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001129 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001130
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301131 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1132 snd_device);
1133 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301134
1135 /*
1136 * Make sure out devices is checked against out codec backend device and
1137 * also in devices against in codec backend. Checking out device against in
1138 * codec backend or vice versa causes issues.
1139 */
1140 if (uc_info->type == PCM_CAPTURE)
1141 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001142 /*
1143 * This function is to make sure that all the active capture usecases
1144 * are always routed to the same input sound device.
1145 * For example, if audio-record and voice-call usecases are currently
1146 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1147 * is received for voice call then we have to make sure that audio-record
1148 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1149 * because of the limitation that two devices cannot be enabled
1150 * at the same time if they share the same backend.
1151 */
1152 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1153 switch_device[i] = false;
1154
1155 list_for_each(node, &adev->usecase_list) {
1156 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301157 /*
1158 * TODO: Enhance below condition to handle BT sco/USB multi recording
1159 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001160 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001161 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301162 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301163 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301164 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001165 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001166 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001167 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1168 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001169 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001170 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001171 switch_device[usecase->id] = true;
1172 num_uc_to_switch++;
1173 }
1174 }
1175
1176 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001177 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001178
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301179 /* Make sure the previous devices to be disabled first and then enable the
1180 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 list_for_each(node, &adev->usecase_list) {
1182 usecase = node_to_item(node, struct audio_usecase, list);
1183 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001184 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001185 }
1186 }
1187
1188 list_for_each(node, &adev->usecase_list) {
1189 usecase = node_to_item(node, struct audio_usecase, list);
1190 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001191 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001192 }
1193 }
1194
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001195 /* Re-route all the usecases on the shared backend other than the
1196 specified usecase to new snd devices */
1197 list_for_each(node, &adev->usecase_list) {
1198 usecase = node_to_item(node, struct audio_usecase, list);
1199 /* Update the in_snd_device only before enabling the audio route */
1200 if (switch_device[usecase->id] ) {
1201 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001202 if (usecase->type != VOICE_CALL) {
1203 /* Update voc calibration before enabling VoIP route */
1204 if (usecase->type == VOIP_CALL)
1205 status = platform_switch_voice_call_device_post(adev->platform,
1206 usecase->out_snd_device,
1207 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301208 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001209 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 }
1211 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 }
1213}
1214
Mingming Yin3a941d42016-02-17 18:08:05 -08001215static void reset_hdmi_sink_caps(struct stream_out *out) {
1216 int i = 0;
1217
1218 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1219 out->supported_channel_masks[i] = 0;
1220 }
1221 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1222 out->supported_formats[i] = 0;
1223 }
1224 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1225 out->supported_sample_rates[i] = 0;
1226 }
1227}
1228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001230static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231{
Mingming Yin3a941d42016-02-17 18:08:05 -08001232 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001233 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234
Mingming Yin3a941d42016-02-17 18:08:05 -08001235 reset_hdmi_sink_caps(out);
1236
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001237 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001238 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001239 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001240 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001241 }
1242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001245 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001246 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001247 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1248 case 6:
1249 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1250 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1251 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1252 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1253 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1254 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001255 break;
1256 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001257 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001258 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 break;
1260 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001261
1262 // check channel format caps
1263 i = 0;
1264 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1265 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1266 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1267 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1268 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1269 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1270 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1271 }
1272
1273 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1274 ALOGV(":%s HDMI supports DTS format", __func__);
1275 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1276 }
1277
1278 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1279 ALOGV(":%s HDMI supports DTS HD format", __func__);
1280 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1281 }
1282
1283
1284 // check sample rate caps
1285 i = 0;
1286 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1287 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1288 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1289 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1290 }
1291 }
1292
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001293 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294}
1295
Alexy Josephb1379942016-01-29 15:49:38 -08001296audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001297 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001298{
1299 struct audio_usecase *usecase;
1300 struct listnode *node;
1301
1302 list_for_each(node, &adev->usecase_list) {
1303 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001304 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001305 ALOGV("%s: usecase id %d", __func__, usecase->id);
1306 return usecase->id;
1307 }
1308 }
1309 return USECASE_INVALID;
1310}
1311
Alexy Josephb1379942016-01-29 15:49:38 -08001312struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001313 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001314{
1315 struct audio_usecase *usecase;
1316 struct listnode *node;
1317
1318 list_for_each(node, &adev->usecase_list) {
1319 usecase = node_to_item(node, struct audio_usecase, list);
1320 if (usecase->id == uc_id)
1321 return usecase;
1322 }
1323 return NULL;
1324}
1325
Dhananjay Kumard4833242016-10-06 22:09:12 +05301326struct stream_in *get_next_active_input(const struct audio_device *adev)
1327{
1328 struct audio_usecase *usecase;
1329 struct listnode *node;
1330
1331 list_for_each_reverse(node, &adev->usecase_list) {
1332 usecase = node_to_item(node, struct audio_usecase, list);
1333 if (usecase->type == PCM_CAPTURE)
1334 return usecase->stream.in;
1335 }
1336 return NULL;
1337}
1338
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301339/*
1340 * is a true native playback active
1341 */
1342bool audio_is_true_native_stream_active(struct audio_device *adev)
1343{
1344 bool active = false;
1345 int i = 0;
1346 struct listnode *node;
1347
1348 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1349 ALOGV("%s:napb: not in true mode or non hdphones device",
1350 __func__);
1351 active = false;
1352 goto exit;
1353 }
1354
1355 list_for_each(node, &adev->usecase_list) {
1356 struct audio_usecase *uc;
1357 uc = node_to_item(node, struct audio_usecase, list);
1358 struct stream_out *curr_out =
1359 (struct stream_out*) uc->stream.out;
1360
1361 if (curr_out && PCM_PLAYBACK == uc->type) {
1362 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1363 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1364 uc->id, curr_out->sample_rate,
1365 curr_out->bit_width,
1366 platform_get_snd_device_name(uc->out_snd_device));
1367
1368 if (is_offload_usecase(uc->id) &&
1369 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1370 active = true;
1371 ALOGD("%s:napb:native stream detected", __func__);
1372 }
1373 }
1374 }
1375exit:
1376 return active;
1377}
1378
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301379/*
1380 * if native DSD playback active
1381 */
1382bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1383{
1384 bool active = false;
1385 struct listnode *node = NULL;
1386 struct audio_usecase *uc = NULL;
1387 struct stream_out *curr_out = NULL;
1388
1389 list_for_each(node, &adev->usecase_list) {
1390 uc = node_to_item(node, struct audio_usecase, list);
1391 curr_out = (struct stream_out*) uc->stream.out;
1392
1393 if (curr_out && PCM_PLAYBACK == uc->type &&
1394 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1395 active = true;
1396 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301397 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301398 }
1399 }
1400 return active;
1401}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301402
1403static bool force_device_switch(struct audio_usecase *usecase)
1404{
1405 bool ret = false;
1406 bool is_it_true_mode = false;
1407
1408 if (is_offload_usecase(usecase->id) &&
1409 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001410 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1411 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1412 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301413 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1414 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1415 (!is_it_true_mode && adev->native_playback_enabled)){
1416 ret = true;
1417 ALOGD("napb: time to toggle native mode");
1418 }
1419 }
1420
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301421 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301422 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1423 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301424 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001425 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301426 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301427 ALOGD("Force a2dp device switch to update new encoder config");
1428 ret = true;
1429 }
1430
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301431 return ret;
1432}
1433
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001434int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001436 snd_device_t out_snd_device = SND_DEVICE_NONE;
1437 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001438 struct audio_usecase *usecase = NULL;
1439 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001440 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001441 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001442 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301445 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1446
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001447 usecase = get_usecase_from_list(adev, uc_id);
1448 if (usecase == NULL) {
1449 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1450 return -EINVAL;
1451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001453 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001454 (usecase->type == VOIP_CALL) ||
1455 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301456 if(usecase->stream.out == NULL) {
1457 ALOGE("%s: stream.out is NULL", __func__);
1458 return -EINVAL;
1459 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001460 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001461 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001462 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 usecase->devices = usecase->stream.out->devices;
1464 } else {
1465 /*
1466 * If the voice call is active, use the sound devices of voice call usecase
1467 * so that it would not result any device switch. All the usecases will
1468 * be switched to new device when select_devices() is called for voice call
1469 * usecase. This is to avoid switching devices for voice call when
1470 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001471 * choose voice call device only if the use case device is
1472 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001474 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001475 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001476 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001477 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1478 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301479 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1480 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001481 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 in_snd_device = vc_usecase->in_snd_device;
1483 out_snd_device = vc_usecase->out_snd_device;
1484 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001485 } else if (voice_extn_compress_voip_is_active(adev)) {
1486 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001487 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001488 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1489 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001490 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001491 in_snd_device = voip_usecase->in_snd_device;
1492 out_snd_device = voip_usecase->out_snd_device;
1493 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001494 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001495 hfp_ucid = audio_extn_hfp_get_usecase();
1496 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001497 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001498 in_snd_device = hfp_usecase->in_snd_device;
1499 out_snd_device = hfp_usecase->out_snd_device;
1500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 }
1502 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301503 if (usecase->stream.out == NULL) {
1504 ALOGE("%s: stream.out is NULL", __func__);
1505 return -EINVAL;
1506 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 usecase->devices = usecase->stream.out->devices;
1508 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001509 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001510 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001511 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001512 if (usecase->stream.out == adev->primary_output &&
1513 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001514 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001515 select_devices(adev, adev->active_input->usecase);
1516 }
1517 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301519 if (usecase->stream.in == NULL) {
1520 ALOGE("%s: stream.in is NULL", __func__);
1521 return -EINVAL;
1522 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523 usecase->devices = usecase->stream.in->device;
1524 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001525 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001526 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001527 if (adev->active_input &&
1528 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301529 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1530 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1531 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001532 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001533 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001534 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1535 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001536 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001537 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001538 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001539 }
1540 }
1541
1542 if (out_snd_device == usecase->out_snd_device &&
1543 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301544
1545 if (!force_device_switch(usecase))
1546 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 }
1548
sangwoobc677242013-08-08 16:53:43 +09001549 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001550 out_snd_device, platform_get_snd_device_name(out_snd_device),
1551 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 /*
1554 * Limitation: While in call, to do a device switch we need to disable
1555 * and enable both RX and TX devices though one of them is same as current
1556 * device.
1557 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001558 if ((usecase->type == VOICE_CALL) &&
1559 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1560 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001561 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001562 }
1563
1564 if (((usecase->type == VOICE_CALL) ||
1565 (usecase->type == VOIP_CALL)) &&
1566 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1567 /* Disable sidetone only if voice/voip call already exists */
1568 if (voice_is_call_state_active(adev) ||
1569 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001570 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001571
1572 /* Disable aanc only if voice call exists */
1573 if (voice_is_call_state_active(adev))
1574 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001575 }
1576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 /* Disable current sound devices */
1578 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001579 disable_audio_route(adev, usecase);
1580 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581 }
1582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001583 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001584 disable_audio_route(adev, usecase);
1585 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 }
1587
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001588 /* Applicable only on the targets that has external modem.
1589 * New device information should be sent to modem before enabling
1590 * the devices to reduce in-call device switch time.
1591 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001592 if ((usecase->type == VOICE_CALL) &&
1593 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1594 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001595 status = platform_switch_voice_call_enable_device_config(adev->platform,
1596 out_snd_device,
1597 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001598 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001600 /* Enable new sound devices */
1601 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001602 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001603 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 }
1605
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001606 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301607 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001608 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001609 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001610
Avinash Vaish71a8b972014-07-24 15:36:33 +05301611 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001612 status = platform_switch_voice_call_device_post(adev->platform,
1613 out_snd_device,
1614 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301615 enable_audio_route_for_voice_usecases(adev, usecase);
1616 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001617
sangwoo170731f2013-06-08 15:36:36 +09001618 usecase->in_snd_device = in_snd_device;
1619 usecase->out_snd_device = out_snd_device;
1620
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301621 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1622 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301623 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001624 if ((24 == usecase->stream.out->bit_width) &&
1625 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1626 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1627 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1628 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1629 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1630 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1631 /*
1632 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1633 * configured device sample rate, if not update the COPP rate to be equal to the
1634 * device sample rate, else open COPP at stream sample rate
1635 */
1636 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1637 usecase->stream.out->sample_rate,
1638 &usecase->stream.out->app_type_cfg.sample_rate);
1639 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1640 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1641 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1642 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1643 }
1644
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001645 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001646 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001647 audio_extn_gef_notify_device_config(
1648 usecase->stream.out->devices,
1649 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001650 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001651 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001652 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301653 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001654 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001655
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001656 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001657 /* Enable aanc only if voice call exists */
1658 if (voice_is_call_state_active(adev))
1659 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1660
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001661 /* Enable sidetone only if other voice/voip call already exists */
1662 if (voice_is_call_state_active(adev) ||
1663 voice_extn_compress_voip_is_started(adev))
1664 voice_set_sidetone(adev, out_snd_device, true);
1665 }
1666
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001667 /* Applicable only on the targets that has external modem.
1668 * Enable device command should be sent to modem only after
1669 * enabling voice call mixer controls
1670 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001671 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001672 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1673 out_snd_device,
1674 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301675 ALOGD("%s: done",__func__);
1676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 return status;
1678}
1679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680static int stop_input_stream(struct stream_in *in)
1681{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301682 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683 struct audio_usecase *uc_info;
1684 struct audio_device *adev = in->dev;
1685
Eric Laurent994a6932013-07-17 11:51:42 -07001686 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001687 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 uc_info = get_usecase_from_list(adev, in->usecase);
1689 if (uc_info == NULL) {
1690 ALOGE("%s: Could not find the usecase (%d) in the list",
1691 __func__, in->usecase);
1692 return -EINVAL;
1693 }
1694
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001695 /* Close in-call recording streams */
1696 voice_check_and_stop_incall_rec_usecase(adev, in);
1697
Eric Laurent150dbfe2013-02-27 14:31:02 -08001698 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001699 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001700
1701 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001702 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001704 list_remove(&uc_info->list);
1705 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001707 adev->active_input = get_next_active_input(adev);
1708
Eric Laurent994a6932013-07-17 11:51:42 -07001709 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710 return ret;
1711}
1712
1713int start_input_stream(struct stream_in *in)
1714{
1715 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001716 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 struct audio_usecase *uc_info;
1718 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301719 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
Mingming Yin2664a5b2015-09-03 10:53:11 -07001721 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1722 if (get_usecase_from_list(adev, usecase) == NULL)
1723 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301724 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1725 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001726
Naresh Tanniru80659832014-06-04 18:17:56 +05301727
1728 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301729 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301730 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301731 goto error_config;
1732 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301733
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001734 /* Check if source matches incall recording usecase criteria */
1735 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1736 if (ret)
1737 goto error_config;
1738 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001739 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1740
1741 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1742 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1743 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001744 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001745 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001746
Eric Laurentb23d5282013-05-14 15:27:20 -07001747 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 if (in->pcm_device_id < 0) {
1749 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1750 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001751 ret = -EINVAL;
1752 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754
1755 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001757
1758 if (!uc_info) {
1759 ret = -ENOMEM;
1760 goto error_config;
1761 }
1762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763 uc_info->id = in->usecase;
1764 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001765 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766 uc_info->devices = in->device;
1767 uc_info->in_snd_device = SND_DEVICE_NONE;
1768 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001770 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301771 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1772 adev->perf_lock_opts,
1773 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001774 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301776 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1777 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001778
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301779 if (audio_extn_cin_attached_usecase(in->usecase)) {
1780 ret = audio_extn_cin_start_input_stream(in);
1781 if (ret)
1782 goto error_open;
1783 else
1784 goto done_open;
1785 }
1786
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001787 unsigned int flags = PCM_IN;
1788 unsigned int pcm_open_retry_count = 0;
1789
1790 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1791 flags |= PCM_MMAP | PCM_NOIRQ;
1792 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001793 } else if (in->realtime) {
1794 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001795 }
1796
1797 while (1) {
1798 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1799 flags, &in->config);
1800 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1801 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1802 if (in->pcm != NULL) {
1803 pcm_close(in->pcm);
1804 in->pcm = NULL;
1805 }
1806 if (pcm_open_retry_count-- == 0) {
1807 ret = -EIO;
1808 goto error_open;
1809 }
1810 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1811 continue;
1812 }
1813 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001815
1816 ALOGV("%s: pcm_prepare", __func__);
1817 ret = pcm_prepare(in->pcm);
1818 if (ret < 0) {
1819 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1820 pcm_close(in->pcm);
1821 in->pcm = NULL;
1822 goto error_open;
1823 }
1824
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001825 register_in_stream(in);
1826 if (in->realtime) {
1827 ret = pcm_start(in->pcm);
1828 if (ret < 0)
1829 goto error_open;
1830 }
1831
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301832done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301833 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001834 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001835
Eric Laurentc8400632013-02-14 19:04:54 -08001836 return ret;
1837
1838error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301839 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001841error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301842 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301843 /*
1844 * sleep 50ms to allow sufficient time for kernel
1845 * drivers to recover incases like SSR.
1846 */
1847 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001849
1850 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851}
1852
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001853void lock_input_stream(struct stream_in *in)
1854{
1855 pthread_mutex_lock(&in->pre_lock);
1856 pthread_mutex_lock(&in->lock);
1857 pthread_mutex_unlock(&in->pre_lock);
1858}
1859
1860void lock_output_stream(struct stream_out *out)
1861{
1862 pthread_mutex_lock(&out->pre_lock);
1863 pthread_mutex_lock(&out->lock);
1864 pthread_mutex_unlock(&out->pre_lock);
1865}
1866
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001867/* must be called with out->lock locked */
1868static int send_offload_cmd_l(struct stream_out* out, int command)
1869{
1870 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1871
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001872 if (!cmd) {
1873 ALOGE("failed to allocate mem for command 0x%x", command);
1874 return -ENOMEM;
1875 }
1876
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001877 ALOGVV("%s %d", __func__, command);
1878
1879 cmd->cmd = command;
1880 list_add_tail(&out->offload_cmd_list, &cmd->node);
1881 pthread_cond_signal(&out->offload_cond);
1882 return 0;
1883}
1884
1885/* must be called iwth out->lock locked */
1886static void stop_compressed_output_l(struct stream_out *out)
1887{
1888 out->offload_state = OFFLOAD_STATE_IDLE;
1889 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001890 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001891 if (out->compr != NULL) {
1892 compress_stop(out->compr);
1893 while (out->offload_thread_blocked) {
1894 pthread_cond_wait(&out->cond, &out->lock);
1895 }
1896 }
1897}
1898
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001899bool is_offload_usecase(audio_usecase_t uc_id)
1900{
1901 unsigned int i;
1902 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1903 if (uc_id == offload_usecases[i])
1904 return true;
1905 }
1906 return false;
1907}
1908
vivek mehta446c3962015-09-14 10:57:35 -07001909static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001910{
vivek mehta446c3962015-09-14 10:57:35 -07001911 audio_usecase_t ret_uc = USECASE_INVALID;
1912 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001913 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001914 if (!adev->multi_offload_enable) {
1915 if (is_direct_pcm)
1916 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1917 else
1918 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001919
vivek mehta446c3962015-09-14 10:57:35 -07001920 pthread_mutex_lock(&adev->lock);
1921 if (get_usecase_from_list(adev, ret_uc) != NULL)
1922 ret_uc = USECASE_INVALID;
1923 pthread_mutex_unlock(&adev->lock);
1924
1925 return ret_uc;
1926 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001927
1928 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001929 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1930 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1931 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1932 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001933 break;
1934 }
1935 }
vivek mehta446c3962015-09-14 10:57:35 -07001936
1937 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1938 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001939}
1940
1941static void free_offload_usecase(struct audio_device *adev,
1942 audio_usecase_t uc_id)
1943{
vivek mehta446c3962015-09-14 10:57:35 -07001944 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001945 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001946
1947 if (!adev->multi_offload_enable)
1948 return;
1949
1950 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1951 if (offload_usecases[offload_uc_index] == uc_id) {
1952 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001953 break;
1954 }
1955 }
1956 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1957}
1958
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959static void *offload_thread_loop(void *context)
1960{
1961 struct stream_out *out = (struct stream_out *) context;
1962 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001963 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1966 set_sched_policy(0, SP_FOREGROUND);
1967 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1968
1969 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001970 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001971 for (;;) {
1972 struct offload_cmd *cmd = NULL;
1973 stream_callback_event_t event;
1974 bool send_callback = false;
1975
1976 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1977 __func__, list_empty(&out->offload_cmd_list),
1978 out->offload_state);
1979 if (list_empty(&out->offload_cmd_list)) {
1980 ALOGV("%s SLEEPING", __func__);
1981 pthread_cond_wait(&out->offload_cond, &out->lock);
1982 ALOGV("%s RUNNING", __func__);
1983 continue;
1984 }
1985
1986 item = list_head(&out->offload_cmd_list);
1987 cmd = node_to_item(item, struct offload_cmd, node);
1988 list_remove(item);
1989
1990 ALOGVV("%s STATE %d CMD %d out->compr %p",
1991 __func__, out->offload_state, cmd->cmd, out->compr);
1992
1993 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1994 free(cmd);
1995 break;
1996 }
1997
1998 if (out->compr == NULL) {
1999 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002000 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002001 pthread_cond_signal(&out->cond);
2002 continue;
2003 }
2004 out->offload_thread_blocked = true;
2005 pthread_mutex_unlock(&out->lock);
2006 send_callback = false;
2007 switch(cmd->cmd) {
2008 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002009 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002010 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002011 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002012 send_callback = true;
2013 event = STREAM_CBK_EVENT_WRITE_READY;
2014 break;
2015 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002016 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302017 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002018 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302019 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002020 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302021 if (ret < 0)
2022 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302023 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302024 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002025 compress_drain(out->compr);
2026 else
2027 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302028 if (ret != -ENETRESET) {
2029 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302030 pthread_mutex_lock(&out->lock);
2031 out->send_new_metadata = 1;
2032 out->send_next_track_params = true;
2033 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302034 event = STREAM_CBK_EVENT_DRAIN_READY;
2035 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2036 } else
2037 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 break;
2039 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002040 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002042 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043 send_callback = true;
2044 event = STREAM_CBK_EVENT_DRAIN_READY;
2045 break;
2046 default:
2047 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2048 break;
2049 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002050 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 out->offload_thread_blocked = false;
2052 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002053 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002054 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002056 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 free(cmd);
2058 }
2059
2060 pthread_cond_signal(&out->cond);
2061 while (!list_empty(&out->offload_cmd_list)) {
2062 item = list_head(&out->offload_cmd_list);
2063 list_remove(item);
2064 free(node_to_item(item, struct offload_cmd, node));
2065 }
2066 pthread_mutex_unlock(&out->lock);
2067
2068 return NULL;
2069}
2070
2071static int create_offload_callback_thread(struct stream_out *out)
2072{
2073 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2074 list_init(&out->offload_cmd_list);
2075 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2076 offload_thread_loop, out);
2077 return 0;
2078}
2079
2080static int destroy_offload_callback_thread(struct stream_out *out)
2081{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002082 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 stop_compressed_output_l(out);
2084 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2085
2086 pthread_mutex_unlock(&out->lock);
2087 pthread_join(out->offload_thread, (void **) NULL);
2088 pthread_cond_destroy(&out->offload_cond);
2089
2090 return 0;
2091}
2092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093static int stop_output_stream(struct stream_out *out)
2094{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302095 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 struct audio_usecase *uc_info;
2097 struct audio_device *adev = out->dev;
2098
Eric Laurent994a6932013-07-17 11:51:42 -07002099 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002100 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 uc_info = get_usecase_from_list(adev, out->usecase);
2102 if (uc_info == NULL) {
2103 ALOGE("%s: Could not find the usecase (%d) in the list",
2104 __func__, out->usecase);
2105 return -EINVAL;
2106 }
2107
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002108 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302109 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002110 if (adev->visualizer_stop_output != NULL)
2111 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002112
2113 audio_extn_dts_remove_state_notifier_node(out->usecase);
2114
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002115 if (adev->offload_effects_stop_output != NULL)
2116 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2117 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002118
Eric Laurent150dbfe2013-02-27 14:31:02 -08002119 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002120 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002121
2122 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002123 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002125 list_remove(&uc_info->list);
2126 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002128 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302129 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002130 ALOGV("Disable passthrough , reset mixer to pcm");
2131 /* NO_PASSTHROUGH */
2132 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002133 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002134 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2135 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002136
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302137 /* Must be called after removing the usecase from list */
2138 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302139 audio_extn_keep_alive_start();
2140
Eric Laurent994a6932013-07-17 11:51:42 -07002141 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 return ret;
2143}
2144
2145int start_output_stream(struct stream_out *out)
2146{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 struct audio_usecase *uc_info;
2149 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302150 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002152 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2153 ret = -EINVAL;
2154 goto error_config;
2155 }
2156
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302157 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2158 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2159 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302160
Naresh Tanniru80659832014-06-04 18:17:56 +05302161 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302162 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302163 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302164 goto error_config;
2165 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302166
Eric Laurentb23d5282013-05-14 15:27:20 -07002167 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 if (out->pcm_device_id < 0) {
2169 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2170 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002171 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002172 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 }
2174
2175 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002176
2177 if (!uc_info) {
2178 ret = -ENOMEM;
2179 goto error_config;
2180 }
2181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 uc_info->id = out->usecase;
2183 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002184 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002185 uc_info->devices = out->devices;
2186 uc_info->in_snd_device = SND_DEVICE_NONE;
2187 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002188 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302190 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2191 adev->perf_lock_opts,
2192 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302193
2194 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2195 audio_extn_keep_alive_stop();
2196 if (audio_extn_passthru_is_enabled() &&
2197 audio_extn_passthru_is_passthrough_stream(out)) {
2198 audio_extn_passthru_on_start(out);
2199 audio_extn_passthru_update_stream_configuration(adev, out);
2200 }
2201 }
2202
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 select_devices(adev, out->usecase);
2204
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002205 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2206 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002207 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002208 unsigned int flags = PCM_OUT;
2209 unsigned int pcm_open_retry_count = 0;
2210 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2211 flags |= PCM_MMAP | PCM_NOIRQ;
2212 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002213 } else if (out->realtime) {
2214 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002215 } else
2216 flags |= PCM_MONOTONIC;
2217
2218 while (1) {
2219 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2220 flags, &out->config);
2221 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2222 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2223 if (out->pcm != NULL) {
2224 pcm_close(out->pcm);
2225 out->pcm = NULL;
2226 }
2227 if (pcm_open_retry_count-- == 0) {
2228 ret = -EIO;
2229 goto error_open;
2230 }
2231 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2232 continue;
2233 }
2234 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002236
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002237 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2238 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002239
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002240 ALOGV("%s: pcm_prepare", __func__);
2241 if (pcm_is_ready(out->pcm)) {
2242 ret = pcm_prepare(out->pcm);
2243 if (ret < 0) {
2244 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2245 pcm_close(out->pcm);
2246 out->pcm = NULL;
2247 goto error_open;
2248 }
2249 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002251 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2252 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002254 out->compr = compress_open(adev->snd_card,
2255 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 COMPRESS_IN, &out->compr_config);
2257 if (out->compr && !is_compress_ready(out->compr)) {
2258 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2259 compress_close(out->compr);
2260 out->compr = NULL;
2261 ret = -EIO;
2262 goto error_open;
2263 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302264 /* compress_open sends params of the track, so reset the flag here */
2265 out->is_compr_metadata_avail = false;
2266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 if (out->offload_callback)
2268 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002269
Fred Oh3f43e742015-03-04 18:42:34 -08002270 /* Since small bufs uses blocking writes, a write will be blocked
2271 for the default max poll time (20s) in the event of an SSR.
2272 Reduce the poll time to observe and deal with SSR faster.
2273 */
Ashish Jain5106d362016-05-11 19:23:33 +05302274 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002275 compress_set_max_poll_wait(out->compr, 1000);
2276 }
2277
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002278 audio_extn_dts_create_state_notifier_node(out->usecase);
2279 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2280 popcount(out->channel_mask),
2281 out->playback_started);
2282
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002283#ifdef DS1_DOLBY_DDP_ENABLED
2284 if (audio_extn_is_dolby_format(out->format))
2285 audio_extn_dolby_send_ddp_endp_params(adev);
2286#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302287 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002288 if (adev->visualizer_start_output != NULL)
2289 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2290 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302291 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002292 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002293 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002295
2296 if (ret == 0) {
2297 register_out_stream(out);
2298 if (out->realtime) {
2299 ret = pcm_start(out->pcm);
2300 if (ret < 0)
2301 goto error_open;
2302 }
2303 }
2304
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302305 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002306 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002307
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002308 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302310 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002312error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302313 /*
2314 * sleep 50ms to allow sufficient time for kernel
2315 * drivers to recover incases like SSR.
2316 */
2317 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002318 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319}
2320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321static int check_input_parameters(uint32_t sample_rate,
2322 audio_format_t format,
2323 int channel_count)
2324{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002325 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302327 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2328 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2329 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002330 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302331 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002332
2333 switch (channel_count) {
2334 case 1:
2335 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302336 case 3:
2337 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002338 case 6:
2339 break;
2340 default:
2341 ret = -EINVAL;
2342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343
2344 switch (sample_rate) {
2345 case 8000:
2346 case 11025:
2347 case 12000:
2348 case 16000:
2349 case 22050:
2350 case 24000:
2351 case 32000:
2352 case 44100:
2353 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302354 case 96000:
2355 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 break;
2357 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002358 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 }
2360
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002361 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362}
2363
2364static size_t get_input_buffer_size(uint32_t sample_rate,
2365 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002366 int channel_count,
2367 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368{
2369 size_t size = 0;
2370
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002371 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2372 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002374 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002375 if (is_low_latency)
2376 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302377
2378 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002380 /* make sure the size is multiple of 32 bytes
2381 * At 48 kHz mono 16-bit PCM:
2382 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2383 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2384 */
2385 size += 0x1f;
2386 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002387
2388 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389}
2390
Ashish Jain058165c2016-09-28 23:18:48 +05302391static size_t get_output_period_size(uint32_t sample_rate,
2392 audio_format_t format,
2393 int channel_count,
2394 int duration /*in millisecs*/)
2395{
2396 size_t size = 0;
2397 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2398
2399 if ((duration == 0) || (sample_rate == 0) ||
2400 (bytes_per_sample == 0) || (channel_count == 0)) {
2401 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2402 bytes_per_sample, channel_count);
2403 return -EINVAL;
2404 }
2405
2406 size = (sample_rate *
2407 duration *
2408 bytes_per_sample *
2409 channel_count) / 1000;
2410 /*
2411 * To have same PCM samples for all channels, the buffer size requires to
2412 * be multiple of (number of channels * bytes per sample)
2413 * For writes to succeed, the buffer must be written at address which is multiple of 32
2414 */
2415 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2416
2417 return (size/(channel_count * bytes_per_sample));
2418}
2419
Ashish Jain5106d362016-05-11 19:23:33 +05302420static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2421{
2422 uint64_t actual_frames_rendered = 0;
2423 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2424
2425 /* This adjustment accounts for buffering after app processor.
2426 * It is based on estimated DSP latency per use case, rather than exact.
2427 */
2428 int64_t platform_latency = platform_render_latency(out->usecase) *
2429 out->sample_rate / 1000000LL;
2430
2431 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2432 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2433 * hence only estimate.
2434 */
2435 int64_t signed_frames = out->written - kernel_buffer_size;
2436
2437 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2438
2439 if (signed_frames > 0)
2440 actual_frames_rendered = signed_frames;
2441
2442 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2443 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2444 (long long int)out->written, (int)kernel_buffer_size,
2445 audio_bytes_per_sample(out->compr_config.codec->format),
2446 popcount(out->channel_mask));
2447
2448 return actual_frames_rendered;
2449}
2450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2452{
2453 struct stream_out *out = (struct stream_out *)stream;
2454
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456}
2457
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002458static int out_set_sample_rate(struct audio_stream *stream __unused,
2459 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460{
2461 return -ENOSYS;
2462}
2463
2464static size_t out_get_buffer_size(const struct audio_stream *stream)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002468 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002470 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2471 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302472 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302473 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002475 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002476 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477}
2478
2479static uint32_t out_get_channels(const struct audio_stream *stream)
2480{
2481 struct stream_out *out = (struct stream_out *)stream;
2482
2483 return out->channel_mask;
2484}
2485
2486static audio_format_t out_get_format(const struct audio_stream *stream)
2487{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488 struct stream_out *out = (struct stream_out *)stream;
2489
2490 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491}
2492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002493static int out_set_format(struct audio_stream *stream __unused,
2494 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495{
2496 return -ENOSYS;
2497}
2498
2499static int out_standby(struct audio_stream *stream)
2500{
2501 struct stream_out *out = (struct stream_out *)stream;
2502 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302504 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2505 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002507 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002509 if (adev->adm_deregister_stream)
2510 adev->adm_deregister_stream(adev->adm_data, out->handle);
2511
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002512 if (is_offload_usecase(out->usecase))
2513 stop_compressed_output_l(out);
2514
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002515 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002517 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2518 voice_extn_compress_voip_close_output_stream(stream);
2519 pthread_mutex_unlock(&adev->lock);
2520 pthread_mutex_unlock(&out->lock);
2521 ALOGD("VOIP output entered standby");
2522 return 0;
2523 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 if (out->pcm) {
2525 pcm_close(out->pcm);
2526 out->pcm = NULL;
2527 }
2528 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002529 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302530 out->send_next_track_params = false;
2531 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002532 out->gapless_mdata.encoder_delay = 0;
2533 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 if (out->compr != NULL) {
2535 compress_close(out->compr);
2536 out->compr = NULL;
2537 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 }
2542 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302543 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 return 0;
2545}
2546
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002547static int out_dump(const struct audio_stream *stream __unused,
2548 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549{
2550 return 0;
2551}
2552
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002553static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2554{
2555 int ret = 0;
2556 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002557
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002558 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002559 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002560 return -EINVAL;
2561 }
2562
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302563 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002564
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002565 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2566 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302567 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002568 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002569 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2570 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302571 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002572 }
2573
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002574 ALOGV("%s new encoder delay %u and padding %u", __func__,
2575 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2576
2577 return 0;
2578}
2579
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002580static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2581{
2582 return out == adev->primary_output || out == adev->voice_tx_output;
2583}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2586{
2587 struct stream_out *out = (struct stream_out *)stream;
2588 struct audio_device *adev = out->dev;
2589 struct str_parms *parms;
2590 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002591 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592
sangwoobc677242013-08-08 16:53:43 +09002593 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002594 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302596 if (!parms)
2597 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002598 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2599 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002601 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002602 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002604 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002605 * When HDMI cable is unplugged the music playback is paused and
2606 * the policy manager sends routing=0. But the audioflinger continues
2607 * to write data until standby time (3sec). As the HDMI core is
2608 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002609 * Avoid this by routing audio to speaker until standby.
2610 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002611 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2612 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302613 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002614 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2615 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302617 /*
2618 * When A2DP is disconnected the
2619 * music playback is paused and the policy manager sends routing=0
2620 * But the audioflingercontinues to write data until standby time
2621 * (3sec). As BT is turned off, the write gets blocked.
2622 * Avoid this by routing audio to speaker until standby.
2623 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002624 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302625 (val == AUDIO_DEVICE_NONE)) {
2626 val = AUDIO_DEVICE_OUT_SPEAKER;
2627 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302628 /* To avoid a2dp to sco overlapping force route BT usecases
2629 * to speaker based on Phone state
2630 */
Ashish Jainc597d102016-12-12 10:31:34 +05302631 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2632 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2633 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2634 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302635 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2636 (adev->mode == AUDIO_MODE_IN_CALL))) {
2637 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2638 val = AUDIO_DEVICE_OUT_SPEAKER;
2639 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002640 /*
2641 * select_devices() call below switches all the usecases on the same
2642 * backend to the new device. Refer to check_usecases_codec_backend() in
2643 * the select_devices(). But how do we undo this?
2644 *
2645 * For example, music playback is active on headset (deep-buffer usecase)
2646 * and if we go to ringtones and select a ringtone, low-latency usecase
2647 * will be started on headset+speaker. As we can't enable headset+speaker
2648 * and headset devices at the same time, select_devices() switches the music
2649 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2650 * So when the ringtone playback is completed, how do we undo the same?
2651 *
2652 * We are relying on the out_set_parameters() call on deep-buffer output,
2653 * once the ringtone playback is ended.
2654 * NOTE: We should not check if the current devices are same as new devices.
2655 * Because select_devices() must be called to switch back the music
2656 * playback to headset.
2657 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002658 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002659 audio_devices_t new_dev = val;
2660 bool same_dev = out->devices == new_dev;
2661 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002663 if (output_drives_call(adev, out)) {
2664 if(!voice_is_in_call(adev)) {
2665 if (adev->mode == AUDIO_MODE_IN_CALL) {
2666 adev->current_call_output = out;
2667 ret = voice_start_call(adev);
2668 }
2669 } else {
2670 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002671 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002672 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002673 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002674
2675 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002676 if (!same_dev) {
2677 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302678 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2679 adev->perf_lock_opts,
2680 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002681 if (adev->adm_on_routing_change)
2682 adev->adm_on_routing_change(adev->adm_data,
2683 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002684 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002685 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302686 if (!same_dev)
2687 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002688 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002689 }
2690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002692 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002694
2695 if (out == adev->primary_output) {
2696 pthread_mutex_lock(&adev->lock);
2697 audio_extn_set_parameters(adev, parms);
2698 pthread_mutex_unlock(&adev->lock);
2699 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002700 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002701 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002702 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002703
2704 audio_extn_dts_create_state_notifier_node(out->usecase);
2705 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2706 popcount(out->channel_mask),
2707 out->playback_started);
2708
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002709 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002710 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002711
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302712 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2713 if (err >= 0) {
2714 strlcpy(out->profile, value, sizeof(out->profile));
2715 ALOGV("updating stream profile with value '%s'", out->profile);
2716 lock_output_stream(out);
2717 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2718 &adev->streams_output_cfg_list,
2719 out->devices, out->flags, out->format,
2720 out->sample_rate, out->bit_width,
2721 out->channel_mask, out->profile,
2722 &out->app_type_cfg);
2723 pthread_mutex_unlock(&out->lock);
2724 }
2725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302727error:
Eric Laurent994a6932013-07-17 11:51:42 -07002728 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 return ret;
2730}
2731
2732static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2733{
2734 struct stream_out *out = (struct stream_out *)stream;
2735 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002736 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 char value[256];
2738 struct str_parms *reply = str_parms_create();
2739 size_t i, j;
2740 int ret;
2741 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002742
2743 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002744 if (reply) {
2745 str_parms_destroy(reply);
2746 }
2747 if (query) {
2748 str_parms_destroy(query);
2749 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002750 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2751 return NULL;
2752 }
2753
Eric Laurent994a6932013-07-17 11:51:42 -07002754 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2756 if (ret >= 0) {
2757 value[0] = '\0';
2758 i = 0;
2759 while (out->supported_channel_masks[i] != 0) {
2760 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2761 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2762 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002763 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002765 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 first = false;
2767 break;
2768 }
2769 }
2770 i++;
2771 }
2772 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2773 str = str_parms_to_str(reply);
2774 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002775 voice_extn_out_get_parameters(out, query, reply);
2776 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002777 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002778 free(str);
2779 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002782
Alexy Joseph62142aa2015-11-16 15:10:34 -08002783
2784 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2785 if (ret >= 0) {
2786 value[0] = '\0';
2787 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2788 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302789 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002790 } else {
2791 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302792 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002793 }
2794 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002795 if (str)
2796 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002797 str = str_parms_to_str(reply);
2798 }
2799
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002800 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2801 if (ret >= 0) {
2802 value[0] = '\0';
2803 i = 0;
2804 first = true;
2805 while (out->supported_formats[i] != 0) {
2806 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2807 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2808 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002809 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002810 }
2811 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2812 first = false;
2813 break;
2814 }
2815 }
2816 i++;
2817 }
2818 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002819 if (str)
2820 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002821 str = str_parms_to_str(reply);
2822 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002823
2824 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2825 if (ret >= 0) {
2826 value[0] = '\0';
2827 i = 0;
2828 first = true;
2829 while (out->supported_sample_rates[i] != 0) {
2830 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2831 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2832 if (!first) {
2833 strlcat(value, "|", sizeof(value));
2834 }
2835 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2836 first = false;
2837 break;
2838 }
2839 }
2840 i++;
2841 }
2842 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2843 if (str)
2844 free(str);
2845 str = str_parms_to_str(reply);
2846 }
2847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848 str_parms_destroy(query);
2849 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002850 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 return str;
2852}
2853
2854static uint32_t out_get_latency(const struct audio_stream_out *stream)
2855{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002856 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002858 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859
Alexy Josephaa54c872014-12-03 02:46:47 -08002860 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002861 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002862 } else if (out->realtime) {
2863 // since the buffer won't be filled up faster than realtime,
2864 // return a smaller number
2865 if (out->config.rate)
2866 period_ms = (out->af_period_multiplier * out->config.period_size *
2867 1000) / (out->config.rate);
2868 else
2869 period_ms = 0;
2870 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002871 } else {
2872 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002874 }
2875
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302876 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002877 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878}
2879
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302880static float AmpToDb(float amplification)
2881{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302882 float db = DSD_VOLUME_MIN_DB;
2883 if (amplification > 0) {
2884 db = 20 * log10(amplification);
2885 if(db < DSD_VOLUME_MIN_DB)
2886 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302887 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302888 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302889}
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891static int out_set_volume(struct audio_stream_out *stream, float left,
2892 float right)
2893{
Eric Laurenta9024de2013-04-04 09:19:12 -07002894 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 int volume[2];
2896
Eric Laurenta9024de2013-04-04 09:19:12 -07002897 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2898 /* only take left channel into account: the API is for stereo anyway */
2899 out->muted = (left == 0.0f);
2900 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002901 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302902 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002903 /*
2904 * Set mute or umute on HDMI passthrough stream.
2905 * Only take left channel into account.
2906 * Mute is 0 and unmute 1
2907 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302908 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302909 } else if (out->format == AUDIO_FORMAT_DSD){
2910 char mixer_ctl_name[128] = "DSD Volume";
2911 struct audio_device *adev = out->dev;
2912 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2913
2914 if (!ctl) {
2915 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2916 __func__, mixer_ctl_name);
2917 return -EINVAL;
2918 }
2919 volume[0] = (int)(AmpToDb(left));
2920 volume[1] = (int)(AmpToDb(right));
2921 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2922 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002923 } else {
2924 char mixer_ctl_name[128];
2925 struct audio_device *adev = out->dev;
2926 struct mixer_ctl *ctl;
2927 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002928 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002930 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2931 "Compress Playback %d Volume", pcm_device_id);
2932 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2933 if (!ctl) {
2934 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2935 __func__, mixer_ctl_name);
2936 return -EINVAL;
2937 }
2938 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2939 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2940 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2941 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002943 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 return -ENOSYS;
2946}
2947
2948static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2949 size_t bytes)
2950{
2951 struct stream_out *out = (struct stream_out *)stream;
2952 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302953 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002954 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002956 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302957
Naresh Tanniru80659832014-06-04 18:17:56 +05302958 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002959
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302960 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302961 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302962 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2963 pthread_mutex_unlock(&out->lock);
2964 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302965 } else {
2966 /* increase written size during SSR to avoid mismatch
2967 * with the written frames count in AF
2968 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002969 // bytes per frame
2970 size_t bpf = audio_bytes_per_sample(out->format) *
2971 audio_channel_count_from_out_mask(out->channel_mask);
2972 if (bpf != 0)
2973 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302974 ALOGD(" %s: sound card is not active/SSR state", __func__);
2975 ret= -EIO;
2976 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302977 }
2978 }
2979
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302980 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302981 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2982 if (audio_bytes_per_sample(out->format) != 0)
2983 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2984 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302985 goto exit;
2986 }
2987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002989 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002990 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002991 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2992 ret = voice_extn_compress_voip_start_output_stream(out);
2993 else
2994 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002995 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002998 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 goto exit;
3000 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003001
3002 if (last_known_cal_step != -1) {
3003 ALOGD("%s: retry previous failed cal level set", __func__);
3004 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007
Ashish Jain81eb2a82015-05-13 10:52:34 +05303008 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003009 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303010 adev->is_channel_status_set = true;
3011 }
3012
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003013 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003014 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003015 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003016 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003017 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3018 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303019 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3020 ALOGD("copl(%p):send next track params in gapless", out);
3021 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3022 out->send_next_track_params = false;
3023 out->is_compr_metadata_avail = false;
3024 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003025 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303026 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303027 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003028
Ashish Jain83a6cc22016-06-28 14:34:17 +05303029 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303030 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303031 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303032 pthread_mutex_unlock(&out->lock);
3033 return -EINVAL;
3034 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303035 audio_format_t dst_format = out->hal_op_format;
3036 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303037
3038 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3039 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3040
Ashish Jain83a6cc22016-06-28 14:34:17 +05303041 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303042 dst_format,
3043 buffer,
3044 src_format,
3045 frames);
3046
Ashish Jain83a6cc22016-06-28 14:34:17 +05303047 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303048 bytes_to_write);
3049
3050 /*Convert written bytes in audio flinger format*/
3051 if (ret > 0)
3052 ret = ((ret * format_to_bitwidth_table[out->format]) /
3053 format_to_bitwidth_table[dst_format]);
3054 }
3055 } else
3056 ret = compress_write(out->compr, buffer, bytes);
3057
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303058 if (ret < 0)
3059 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303060 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303061 /*msg to cb thread only if non blocking write is enabled*/
3062 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303063 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303065 } else if (-ENETRESET == ret) {
3066 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3067 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3068 pthread_mutex_unlock(&out->lock);
3069 out_standby(&out->stream.common);
3070 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 }
Ashish Jain5106d362016-05-11 19:23:33 +05303072 if ( ret == (ssize_t)bytes && !out->non_blocking)
3073 out->written += bytes;
3074
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303075 /* Call compr start only when non-zero bytes of data is there to be rendered */
3076 if (!out->playback_started && ret > 0) {
3077 int status = compress_start(out->compr);
3078 if (status < 0) {
3079 ret = status;
3080 ALOGE("%s: compr start failed with err %d", __func__, errno);
3081 goto exit;
3082 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003083 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084 out->playback_started = 1;
3085 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003086
3087 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3088 popcount(out->channel_mask),
3089 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 }
3091 pthread_mutex_unlock(&out->lock);
3092 return ret;
3093 } else {
3094 if (out->pcm) {
3095 if (out->muted)
3096 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003097
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303098 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003099
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003100 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003101
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003102 if (out->config.rate)
3103 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3104 out->config.rate;
3105
3106 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3107
3108 request_out_focus(out, ns);
3109
3110 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003111 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003112 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303113 out->convert_buffer != NULL) {
3114
3115 memcpy_by_audio_format(out->convert_buffer,
3116 out->hal_op_format,
3117 buffer,
3118 out->hal_ip_format,
3119 out->config.period_size * out->config.channels);
3120
3121 ret = pcm_write(out->pcm, out->convert_buffer,
3122 (out->config.period_size *
3123 out->config.channels *
3124 format_to_bitwidth_table[out->hal_op_format]));
3125 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003126 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303127 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003128
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003129 release_out_focus(out);
3130
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303131 if (ret < 0)
3132 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303133 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3134 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3135 else
3136 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 }
3139
3140exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303141 /* ToDo: There may be a corner case when SSR happens back to back during
3142 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303143 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303144 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145 }
3146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 pthread_mutex_unlock(&out->lock);
3148
3149 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003150 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003151 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303152 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303153 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303154 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303155 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303156 out->standby = true;
3157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303159 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3160 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3161 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 }
3163 return bytes;
3164}
3165
3166static int out_get_render_position(const struct audio_stream_out *stream,
3167 uint32_t *dsp_frames)
3168{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303170 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003171
3172 if (dsp_frames == NULL)
3173 return -EINVAL;
3174
3175 *dsp_frames = 0;
3176 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003177 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303178
3179 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3180 * this operation and adev_close_output_stream(where out gets reset).
3181 */
3182 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3183 *dsp_frames = get_actual_pcm_frames_rendered(out);
3184 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3185 return 0;
3186 }
3187
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003188 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303189 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303190 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303192 if (ret < 0)
3193 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003194 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303195 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003196 }
3197 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303198 if (-ENETRESET == ret) {
3199 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3200 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3201 return -EINVAL;
3202 } else if(ret < 0) {
3203 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3204 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303205 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3206 /*
3207 * Handle corner case where compress session is closed during SSR
3208 * and timestamp is queried
3209 */
3210 ALOGE(" ERROR: sound card not active, return error");
3211 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303212 } else {
3213 return 0;
3214 }
Zhou Song32a556e2015-05-05 10:46:56 +08003215 } else if (audio_is_linear_pcm(out->format)) {
3216 *dsp_frames = out->written;
3217 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003218 } else
3219 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220}
3221
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003222static int out_add_audio_effect(const struct audio_stream *stream __unused,
3223 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224{
3225 return 0;
3226}
3227
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003228static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3229 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230{
3231 return 0;
3232}
3233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003234static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3235 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236{
3237 return -EINVAL;
3238}
3239
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003240static int out_get_presentation_position(const struct audio_stream_out *stream,
3241 uint64_t *frames, struct timespec *timestamp)
3242{
3243 struct stream_out *out = (struct stream_out *)stream;
3244 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003245 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003246
Ashish Jain5106d362016-05-11 19:23:33 +05303247 /* below piece of code is not guarded against any lock because audioFliner serializes
3248 * this operation and adev_close_output_stream( where out gets reset).
3249 */
3250 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3251 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3252 *frames = get_actual_pcm_frames_rendered(out);
3253 /* this is the best we can do */
3254 clock_gettime(CLOCK_MONOTONIC, timestamp);
3255 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3256 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3257 return 0;
3258 }
3259
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003260 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003261
Ashish Jain5106d362016-05-11 19:23:33 +05303262 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3263 ret = compress_get_tstamp(out->compr, &dsp_frames,
3264 &out->sample_rate);
3265 ALOGVV("%s rendered frames %ld sample_rate %d",
3266 __func__, dsp_frames, out->sample_rate);
3267 *frames = dsp_frames;
3268 if (ret < 0)
3269 ret = -errno;
3270 if (-ENETRESET == ret) {
3271 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3272 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3273 ret = -EINVAL;
3274 } else
3275 ret = 0;
3276 /* this is the best we can do */
3277 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003278 } else {
3279 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003280 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003281 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3282 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003283 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003284 // This adjustment accounts for buffering after app processor.
3285 // It is based on estimated DSP latency per use case, rather than exact.
3286 signed_frames -=
3287 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3288
Eric Laurent949a0892013-09-20 09:20:13 -07003289 // It would be unusual for this value to be negative, but check just in case ...
3290 if (signed_frames >= 0) {
3291 *frames = signed_frames;
3292 ret = 0;
3293 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003294 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303295 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3296 *frames = out->written;
3297 clock_gettime(CLOCK_MONOTONIC, timestamp);
3298 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003299 }
3300 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003301 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003302 return ret;
3303}
3304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305static int out_set_callback(struct audio_stream_out *stream,
3306 stream_callback_t callback, void *cookie)
3307{
3308 struct stream_out *out = (struct stream_out *)stream;
3309
3310 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003311 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003312 out->offload_callback = callback;
3313 out->offload_cookie = cookie;
3314 pthread_mutex_unlock(&out->lock);
3315 return 0;
3316}
3317
3318static int out_pause(struct audio_stream_out* stream)
3319{
3320 struct stream_out *out = (struct stream_out *)stream;
3321 int status = -ENOSYS;
3322 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003323 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003324 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003325 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303327 struct audio_device *adev = out->dev;
3328 int snd_scard_state = get_snd_card_state(adev);
3329
3330 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3331 status = compress_pause(out->compr);
3332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003333 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003334
Mingming Yin21854652016-04-13 11:54:02 -07003335 if (audio_extn_passthru_is_active()) {
3336 ALOGV("offload use case, pause passthru");
3337 audio_extn_passthru_on_pause(out);
3338 }
3339
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303340 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003341 audio_extn_dts_notify_playback_state(out->usecase, 0,
3342 out->sample_rate, popcount(out->channel_mask),
3343 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003344 }
3345 pthread_mutex_unlock(&out->lock);
3346 }
3347 return status;
3348}
3349
3350static int out_resume(struct audio_stream_out* stream)
3351{
3352 struct stream_out *out = (struct stream_out *)stream;
3353 int status = -ENOSYS;
3354 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003355 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003356 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003357 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003358 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003359 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303360 struct audio_device *adev = out->dev;
3361 int snd_scard_state = get_snd_card_state(adev);
3362
Mingming Yin21854652016-04-13 11:54:02 -07003363 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3364 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3365 pthread_mutex_lock(&out->dev->lock);
3366 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003367 pthread_mutex_unlock(&out->dev->lock);
3368 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303369 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003370 }
3371 if (!status) {
3372 out->offload_state = OFFLOAD_STATE_PLAYING;
3373 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303374 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003375 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3376 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003377 }
3378 pthread_mutex_unlock(&out->lock);
3379 }
3380 return status;
3381}
3382
3383static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3384{
3385 struct stream_out *out = (struct stream_out *)stream;
3386 int status = -ENOSYS;
3387 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003388 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003389 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003390 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3391 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3392 else
3393 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3394 pthread_mutex_unlock(&out->lock);
3395 }
3396 return status;
3397}
3398
3399static int out_flush(struct audio_stream_out* stream)
3400{
3401 struct stream_out *out = (struct stream_out *)stream;
3402 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003403 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003404 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003405 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003406 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3407 stop_compressed_output_l(out);
3408 out->written = 0;
3409 } else {
3410 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3411 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003413 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 return 0;
3415 }
3416 return -ENOSYS;
3417}
3418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419/** audio_stream_in implementation **/
3420static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3421{
3422 struct stream_in *in = (struct stream_in *)stream;
3423
3424 return in->config.rate;
3425}
3426
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003427static int in_set_sample_rate(struct audio_stream *stream __unused,
3428 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429{
3430 return -ENOSYS;
3431}
3432
3433static size_t in_get_buffer_size(const struct audio_stream *stream)
3434{
3435 struct stream_in *in = (struct stream_in *)stream;
3436
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003437 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3438 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003439 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3440 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303441 else if(audio_extn_cin_attached_usecase(in->usecase))
3442 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003443
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003444 return in->config.period_size * in->af_period_multiplier *
3445 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446}
3447
3448static uint32_t in_get_channels(const struct audio_stream *stream)
3449{
3450 struct stream_in *in = (struct stream_in *)stream;
3451
3452 return in->channel_mask;
3453}
3454
3455static audio_format_t in_get_format(const struct audio_stream *stream)
3456{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003457 struct stream_in *in = (struct stream_in *)stream;
3458
3459 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460}
3461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003462static int in_set_format(struct audio_stream *stream __unused,
3463 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464{
3465 return -ENOSYS;
3466}
3467
3468static int in_standby(struct audio_stream *stream)
3469{
3470 struct stream_in *in = (struct stream_in *)stream;
3471 struct audio_device *adev = in->dev;
3472 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303473 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3474 stream, in->usecase, use_case_table[in->usecase]);
3475
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003476 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003477 if (!in->standby && in->is_st_session) {
3478 ALOGD("%s: sound trigger pcm stop lab", __func__);
3479 audio_extn_sound_trigger_stop_lab(in);
3480 in->standby = 1;
3481 }
3482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003484 if (adev->adm_deregister_stream)
3485 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3486
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003487 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003489 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3490 voice_extn_compress_voip_close_input_stream(stream);
3491 ALOGD("VOIP input entered standby");
3492 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303493 if (audio_extn_cin_attached_usecase(in->usecase))
3494 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003495 if (in->pcm) {
3496 pcm_close(in->pcm);
3497 in->pcm = NULL;
3498 }
3499 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003500 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003501 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 }
3503 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003504 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 return status;
3506}
3507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003508static int in_dump(const struct audio_stream *stream __unused,
3509 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
3511 return 0;
3512}
3513
3514static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3515{
3516 struct stream_in *in = (struct stream_in *)stream;
3517 struct audio_device *adev = in->dev;
3518 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003520 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303522 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 parms = str_parms_create_str(kvpairs);
3524
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303525 if (!parms)
3526 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003527 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003528 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003529
3530 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3531 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 val = atoi(value);
3533 /* no audio source uses val == 0 */
3534 if ((in->source != val) && (val != 0)) {
3535 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003536 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3537 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3538 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003539 (in->config.rate == 8000 || in->config.rate == 16000 ||
3540 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003541 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003542 err = voice_extn_compress_voip_open_input_stream(in);
3543 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003544 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003545 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003546 }
3547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 }
3549 }
3550
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003551 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3552 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003554 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 in->device = val;
3556 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003557 if (!in->standby && !in->is_st_session) {
3558 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003559 if (adev->adm_on_routing_change)
3560 adev->adm_on_routing_change(adev->adm_data,
3561 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003562 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003563 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 }
3565 }
3566
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303567 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3568 if (err >= 0) {
3569 strlcpy(in->profile, value, sizeof(in->profile));
3570 ALOGV("updating stream profile with value '%s'", in->profile);
3571 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3572 &adev->streams_input_cfg_list,
3573 in->device, in->flags, in->format,
3574 in->sample_rate, in->bit_width,
3575 in->profile, &in->app_type_cfg);
3576 }
3577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003579 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580
3581 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303582error:
Eric Laurent994a6932013-07-17 11:51:42 -07003583 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584 return ret;
3585}
3586
3587static char* in_get_parameters(const struct audio_stream *stream,
3588 const char *keys)
3589{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003590 struct stream_in *in = (struct stream_in *)stream;
3591 struct str_parms *query = str_parms_create_str(keys);
3592 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003593 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003594
3595 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003596 if (reply) {
3597 str_parms_destroy(reply);
3598 }
3599 if (query) {
3600 str_parms_destroy(query);
3601 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003602 ALOGE("in_get_parameters: failed to create query or reply");
3603 return NULL;
3604 }
3605
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003606 ALOGV("%s: enter: keys - %s", __func__, keys);
3607
3608 voice_extn_in_get_parameters(in, query, reply);
3609
3610 str = str_parms_to_str(reply);
3611 str_parms_destroy(query);
3612 str_parms_destroy(reply);
3613
3614 ALOGV("%s: exit: returns - %s", __func__, str);
3615 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616}
3617
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003618static int in_set_gain(struct audio_stream_in *stream __unused,
3619 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620{
3621 return 0;
3622}
3623
3624static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3625 size_t bytes)
3626{
3627 struct stream_in *in = (struct stream_in *)stream;
3628 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303629 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303630 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303631 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003633 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303634
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003635 if (in->is_st_session) {
3636 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3637 /* Read from sound trigger HAL */
3638 audio_extn_sound_trigger_read(in, buffer, bytes);
3639 pthread_mutex_unlock(&in->lock);
3640 return bytes;
3641 }
3642
Ashish Jainbbce4322016-02-16 13:25:27 +05303643 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003644 ALOGD(" %s: sound card is not active/SSR state", __func__);
3645 ret= -EIO;;
3646 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303647 }
3648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003650 pthread_mutex_lock(&adev->lock);
3651 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3652 ret = voice_extn_compress_voip_start_input_stream(in);
3653 else
3654 ret = start_input_stream(in);
3655 pthread_mutex_unlock(&adev->lock);
3656 if (ret != 0) {
3657 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 }
3659 in->standby = 0;
3660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003662 // what's the duration requested by the client?
3663 long ns = 0;
3664
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303665 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003666 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3667 in->config.rate;
3668
3669 request_in_focus(in, ns);
3670 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003671
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303672 if (audio_extn_cin_attached_usecase(in->usecase)) {
3673 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3674 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303675 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003676 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303677 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003678 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003679 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003680 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303681 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003682 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303683 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3684 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3685 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3686 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303687 ret = -EINVAL;
3688 goto exit;
3689 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303690 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303691 ret = -errno;
3692 }
3693 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303694 /* bytes read is always set to bytes for non compress usecases */
3695 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 }
3697
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003698 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 /*
3701 * Instead of writing zeroes here, we could trust the hardware
3702 * to always provide zeroes when muted.
3703 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303704 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3705 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 memset(buffer, 0, bytes);
3707
3708exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303709 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303710 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003711 if (-ENETRESET == ret)
3712 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 pthread_mutex_unlock(&in->lock);
3715
3716 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303717 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303718 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303719 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303720 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303721 in->standby = true;
3722 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303723 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003725 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303726 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303727 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303729 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730}
3731
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003732static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733{
3734 return 0;
3735}
3736
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003737static int add_remove_audio_effect(const struct audio_stream *stream,
3738 effect_handle_t effect,
3739 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003741 struct stream_in *in = (struct stream_in *)stream;
3742 int status = 0;
3743 effect_descriptor_t desc;
3744
3745 status = (*effect)->get_descriptor(effect, &desc);
3746 if (status != 0)
3747 return status;
3748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003749 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003750 pthread_mutex_lock(&in->dev->lock);
3751 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3752 in->enable_aec != enable &&
3753 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3754 in->enable_aec = enable;
3755 if (!in->standby)
3756 select_devices(in->dev, in->usecase);
3757 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003758 if (in->enable_ns != enable &&
3759 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3760 in->enable_ns = enable;
3761 if (!in->standby)
3762 select_devices(in->dev, in->usecase);
3763 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003764 pthread_mutex_unlock(&in->dev->lock);
3765 pthread_mutex_unlock(&in->lock);
3766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 return 0;
3768}
3769
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003770static int in_add_audio_effect(const struct audio_stream *stream,
3771 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772{
Eric Laurent994a6932013-07-17 11:51:42 -07003773 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003774 return add_remove_audio_effect(stream, effect, true);
3775}
3776
3777static int in_remove_audio_effect(const struct audio_stream *stream,
3778 effect_handle_t effect)
3779{
Eric Laurent994a6932013-07-17 11:51:42 -07003780 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003781 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782}
3783
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303784int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 audio_io_handle_t handle,
3786 audio_devices_t devices,
3787 audio_output_flags_t flags,
3788 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003789 struct audio_stream_out **stream_out,
3790 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791{
3792 struct audio_device *adev = (struct audio_device *)dev;
3793 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303794 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003795 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303798
3799 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3800 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003801 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303802 return -EINVAL;
3803 }
3804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3806
Mingming Yin3a941d42016-02-17 18:08:05 -08003807 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3808 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303809 devices, flags, &out->stream);
3810
3811
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003812 if (!out) {
3813 return -ENOMEM;
3814 }
3815
Haynes Mathew George204045b2015-02-25 20:32:03 -08003816 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003817 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003818 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 if (devices == AUDIO_DEVICE_NONE)
3821 devices = AUDIO_DEVICE_OUT_SPEAKER;
3822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 out->flags = flags;
3824 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003825 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003826 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003827 out->sample_rate = config->sample_rate;
3828 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3829 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003830 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003831 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003832 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303833 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834
Mingming Yin3a941d42016-02-17 18:08:05 -08003835 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3836 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3837 pthread_mutex_lock(&adev->lock);
3838 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3839 ret = read_hdmi_sink_caps(out);
3840 pthread_mutex_unlock(&adev->lock);
3841 if (ret != 0) {
3842 if (ret == -ENOSYS) {
3843 /* ignore and go with default */
3844 ret = 0;
3845 } else {
3846 ALOGE("error reading hdmi sink caps");
3847 goto error_open;
3848 }
3849 }
3850 }
3851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003853 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303854 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3855 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003856 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3857 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3858
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003859 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003860 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3861 /*
3862 * Do not handle stereo output in Multi-channel cases
3863 * Stereo case is handled in normal playback path
3864 */
3865 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3866 ret = AUDIO_CHANNEL_OUT_STEREO;
3867 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003868
3869 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3870 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003871 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003872 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003873 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003874
3875 if (config->sample_rate == 0)
3876 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3877 if (config->channel_mask == 0)
3878 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003879 if (config->format == 0)
3880 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003881
3882 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003883 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003884 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3886 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003888 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003890 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003891 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003892 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003893 ret = voice_extn_compress_voip_open_output_stream(out);
3894 if (ret != 0) {
3895 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3896 __func__, ret);
3897 goto error_open;
3898 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003899 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3900 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3903 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3904 ALOGE("%s: Unsupported Offload information", __func__);
3905 ret = -EINVAL;
3906 goto error_open;
3907 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003908
Mingming Yin3a941d42016-02-17 18:08:05 -08003909 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003910 if(config->offload_info.format == 0)
3911 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003912 if (config->offload_info.sample_rate == 0)
3913 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003914 }
3915
Mingming Yin90310102013-11-13 16:57:00 -08003916 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303917 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003918 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003919 ret = -EINVAL;
3920 goto error_open;
3921 }
3922
3923 out->compr_config.codec = (struct snd_codec *)
3924 calloc(1, sizeof(struct snd_codec));
3925
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003926 if (!out->compr_config.codec) {
3927 ret = -ENOMEM;
3928 goto error_open;
3929 }
3930
vivek mehta0ea887a2015-08-26 14:01:20 -07003931 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303932 out->stream.pause = out_pause;
3933 out->stream.flush = out_flush;
3934 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003935 out->usecase = get_offload_usecase(adev, true);
3936 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003937 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003938 out->stream.set_callback = out_set_callback;
3939 out->stream.pause = out_pause;
3940 out->stream.resume = out_resume;
3941 out->stream.drain = out_drain;
3942 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003943 out->usecase = get_offload_usecase(adev, false);
3944 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003945 }
vivek mehta446c3962015-09-14 10:57:35 -07003946
3947 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003948 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3949 config->format == 0 && config->sample_rate == 0 &&
3950 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003951 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003952 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3953 } else {
3954 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3955 ret = -EEXIST;
3956 goto error_open;
3957 }
vivek mehta446c3962015-09-14 10:57:35 -07003958 }
3959
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 if (config->offload_info.channel_mask)
3961 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003962 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003963 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003964 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003965 } else {
3966 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3967 ret = -EINVAL;
3968 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003969 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003970
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003971 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003972 out->sample_rate = config->offload_info.sample_rate;
3973
Mingming Yin3ee55c62014-08-04 14:23:35 -07003974 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303976 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3977 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3978 audio_extn_dolby_send_ddp_endp_params(adev);
3979 audio_extn_dolby_set_dmid(adev);
3980 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003981
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003982 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003983 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 out->compr_config.codec->bit_rate =
3985 config->offload_info.bit_rate;
3986 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303987 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003988 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303989 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003990 /*TODO: Do we need to change it for passthrough */
3991 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003992
Manish Dewangana6fc5442015-08-24 20:30:31 +05303993 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3994 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05303995 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05303996 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05303997 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
3998 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303999
4000 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4001 AUDIO_FORMAT_PCM) {
4002
4003 /*Based on platform support, configure appropriate alsa format for corresponding
4004 *hal input format.
4005 */
4006 out->compr_config.codec->format = hal_format_to_alsa(
4007 config->offload_info.format);
4008
Ashish Jain83a6cc22016-06-28 14:34:17 +05304009 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304010 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304011 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304012
4013 /*for direct PCM playback populate bit_width based on selected alsa format as
4014 *hal input format and alsa format might differ based on platform support.
4015 */
4016 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304017 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304018
4019 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4020
4021 /* Check if alsa session is configured with the same format as HAL input format,
4022 * if not then derive correct fragment size needed to accomodate the
4023 * conversion of HAL input format to alsa format.
4024 */
4025 audio_extn_utils_update_direct_pcm_fragment_size(out);
4026
4027 /*if hal input and output fragment size is different this indicates HAL input format is
4028 *not same as the alsa format
4029 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304030 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304031 /*Allocate a buffer to convert input data to the alsa configured format.
4032 *size of convert buffer is equal to the size required to hold one fragment size
4033 *worth of pcm data, this is because flinger does not write more than fragment_size
4034 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304035 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4036 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304037 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4038 ret = -ENOMEM;
4039 goto error_open;
4040 }
4041 }
4042 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4043 out->compr_config.fragment_size =
4044 audio_extn_passthru_get_buffer_size(&config->offload_info);
4045 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4046 } else {
4047 out->compr_config.fragment_size =
4048 platform_get_compress_offload_buffer_size(&config->offload_info);
4049 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4050 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004051
Amit Shekhar6f461b12014-08-01 14:52:58 -07004052 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304053 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004055 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4056 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004057
Alexy Josephaa54c872014-12-03 02:46:47 -08004058
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004059 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304060 out->send_next_track_params = false;
4061 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004062 out->offload_state = OFFLOAD_STATE_IDLE;
4063 out->playback_started = 0;
4064
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004065 audio_extn_dts_create_state_notifier_node(out->usecase);
4066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004067 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4068 __func__, config->offload_info.version,
4069 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304070
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304071 /* Check if DSD audio format is supported in codec
4072 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304073 */
4074
4075 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304076 (!platform_check_codec_dsd_support(adev->platform) ||
4077 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304078 ret = -EINVAL;
4079 goto error_open;
4080 }
4081
Ashish Jain5106d362016-05-11 19:23:33 +05304082 /* Disable gapless if any of the following is true
4083 * passthrough playback
4084 * AV playback
4085 * Direct PCM playback
4086 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304087 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304088 (config->format == AUDIO_FORMAT_DSD) ||
4089 config->offload_info.has_video ||
4090 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304091 check_and_set_gapless_mode(adev, false);
4092 } else
4093 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004094
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304095 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004096 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4097 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304098 if (config->format == AUDIO_FORMAT_DSD) {
4099 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4100 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4101 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004102
4103 create_offload_callback_thread(out);
4104
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004105 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304106 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004107 if (ret != 0) {
4108 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4109 __func__, ret);
4110 goto error_open;
4111 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004112 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4113 if (config->sample_rate == 0)
4114 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4115 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4116 config->sample_rate != 8000) {
4117 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4118 ret = -EINVAL;
4119 goto error_open;
4120 }
4121 out->sample_rate = config->sample_rate;
4122 out->config.rate = config->sample_rate;
4123 if (config->format == AUDIO_FORMAT_DEFAULT)
4124 config->format = AUDIO_FORMAT_PCM_16_BIT;
4125 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4126 config->format = AUDIO_FORMAT_PCM_16_BIT;
4127 ret = -EINVAL;
4128 goto error_open;
4129 }
4130 out->format = config->format;
4131 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4132 out->config = pcm_config_afe_proxy_playback;
4133 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004134 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304135 unsigned int channels = 0;
4136 /*Update config params to default if not set by the caller*/
4137 if (config->sample_rate == 0)
4138 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4139 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4140 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4141 if (config->format == AUDIO_FORMAT_DEFAULT)
4142 config->format = AUDIO_FORMAT_PCM_16_BIT;
4143
4144 channels = audio_channel_count_from_out_mask(out->channel_mask);
4145
Ashish Jain83a6cc22016-06-28 14:34:17 +05304146 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4147 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004148 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4149 out->flags);
4150 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304151 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4152 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4153 out->config = pcm_config_low_latency;
4154 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4155 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4156 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304157 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4158 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4159 if (out->config.period_size <= 0) {
4160 ALOGE("Invalid configuration period size is not valid");
4161 ret = -EINVAL;
4162 goto error_open;
4163 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304164 } else {
4165 /* primary path is the default path selected if no other outputs are available/suitable */
4166 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4167 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4168 }
4169 out->hal_ip_format = format = out->format;
4170 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4171 out->hal_op_format = pcm_format_to_hal(out->config.format);
4172 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4173 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004174 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304175 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304176 if (out->hal_ip_format != out->hal_op_format) {
4177 uint32_t buffer_size = out->config.period_size *
4178 format_to_bitwidth_table[out->hal_op_format] *
4179 out->config.channels;
4180 out->convert_buffer = calloc(1, buffer_size);
4181 if (out->convert_buffer == NULL){
4182 ALOGE("Allocation failed for convert buffer for size %d",
4183 out->compr_config.fragment_size);
4184 ret = -ENOMEM;
4185 goto error_open;
4186 }
4187 ALOGD("Convert buffer allocated of size %d", buffer_size);
4188 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189 }
4190
Ashish Jain83a6cc22016-06-28 14:34:17 +05304191 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4192 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4193
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004194 /* TODO remove this hardcoding and check why width is zero*/
4195 if (out->bit_width == 0)
4196 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304197 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004198 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004199 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304200 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304201 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004202 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4203 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4204 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004205 if(adev->primary_output == NULL)
4206 adev->primary_output = out;
4207 else {
4208 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004209 ret = -EEXIST;
4210 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004211 }
4212 }
4213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214 /* Check if this usecase is already existing */
4215 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004216 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4217 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004220 ret = -EEXIST;
4221 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222 }
4223 pthread_mutex_unlock(&adev->lock);
4224
4225 out->stream.common.get_sample_rate = out_get_sample_rate;
4226 out->stream.common.set_sample_rate = out_set_sample_rate;
4227 out->stream.common.get_buffer_size = out_get_buffer_size;
4228 out->stream.common.get_channels = out_get_channels;
4229 out->stream.common.get_format = out_get_format;
4230 out->stream.common.set_format = out_set_format;
4231 out->stream.common.standby = out_standby;
4232 out->stream.common.dump = out_dump;
4233 out->stream.common.set_parameters = out_set_parameters;
4234 out->stream.common.get_parameters = out_get_parameters;
4235 out->stream.common.add_audio_effect = out_add_audio_effect;
4236 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4237 out->stream.get_latency = out_get_latency;
4238 out->stream.set_volume = out_set_volume;
4239 out->stream.write = out_write;
4240 out->stream.get_render_position = out_get_render_position;
4241 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004242 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004244 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004246 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004247 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248
4249 config->format = out->stream.common.get_format(&out->stream.common);
4250 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4251 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4252
4253 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304254 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004255 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004256
4257 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4258 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4259 popcount(out->channel_mask), out->playback_started);
4260
Eric Laurent994a6932013-07-17 11:51:42 -07004261 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004263
4264error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304265 if (out->convert_buffer)
4266 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004267 free(out);
4268 *stream_out = NULL;
4269 ALOGD("%s: exit: ret %d", __func__, ret);
4270 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271}
4272
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304273void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274 struct audio_stream_out *stream)
4275{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004276 struct stream_out *out = (struct stream_out *)stream;
4277 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004278 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004279
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304280 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4281
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004282 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304283 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004284 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304285 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004286 if(ret != 0)
4287 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4288 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004289 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004290 out_standby(&stream->common);
4291
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004292 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004293 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004294 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004295 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004296 if (out->compr_config.codec != NULL)
4297 free(out->compr_config.codec);
4298 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004299
Ashish Jain83a6cc22016-06-28 14:34:17 +05304300 if (out->convert_buffer != NULL) {
4301 free(out->convert_buffer);
4302 out->convert_buffer = NULL;
4303 }
4304
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004305 if (adev->voice_tx_output == out)
4306 adev->voice_tx_output = NULL;
4307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004308 pthread_cond_destroy(&out->cond);
4309 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004311 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312}
4313
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004314static void close_compress_sessions(struct audio_device *adev)
4315{
Mingming Yin7b762e72015-03-04 13:47:32 -08004316 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304317 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004318 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004319 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304320
4321 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004322 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304323 if (is_offload_usecase(usecase->id)) {
4324 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004325 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4326 out = usecase->stream.out;
4327 pthread_mutex_unlock(&adev->lock);
4328 out_standby(&out->stream.common);
4329 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004330 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004331 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304332 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004333 }
4334 pthread_mutex_unlock(&adev->lock);
4335}
4336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4338{
4339 struct audio_device *adev = (struct audio_device *)dev;
4340 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004342 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004343 int ret;
4344 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004346 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304349 if (!parms)
4350 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004351 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4352 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304353 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304354 if (strstr(snd_card_status, "OFFLINE")) {
4355 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304356 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004357 //close compress sessions on OFFLINE status
4358 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304359 } else if (strstr(snd_card_status, "ONLINE")) {
4360 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304361 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004362 //send dts hpx license if enabled
4363 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304364 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304365 }
4366
4367 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004368 status = voice_set_parameters(adev, parms);
4369 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004370 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004372 status = platform_set_parameters(adev->platform, parms);
4373 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004374 goto done;
4375
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004376 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4377 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004378 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4380 adev->bluetooth_nrec = true;
4381 else
4382 adev->bluetooth_nrec = false;
4383 }
4384
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004385 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4386 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4388 adev->screen_off = false;
4389 else
4390 adev->screen_off = true;
4391 }
4392
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004393 ret = str_parms_get_int(parms, "rotation", &val);
4394 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004395 bool reverse_speakers = false;
4396 switch(val) {
4397 // FIXME: note that the code below assumes that the speakers are in the correct placement
4398 // relative to the user when the device is rotated 90deg from its default rotation. This
4399 // assumption is device-specific, not platform-specific like this code.
4400 case 270:
4401 reverse_speakers = true;
4402 break;
4403 case 0:
4404 case 90:
4405 case 180:
4406 break;
4407 default:
4408 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004409 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004410 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004411 if (status == 0) {
4412 if (adev->speaker_lr_swap != reverse_speakers) {
4413 adev->speaker_lr_swap = reverse_speakers;
4414 // only update the selected device if there is active pcm playback
4415 struct audio_usecase *usecase;
4416 struct listnode *node;
4417 list_for_each(node, &adev->usecase_list) {
4418 usecase = node_to_item(node, struct audio_usecase, list);
4419 if (usecase->type == PCM_PLAYBACK) {
4420 select_devices(adev, usecase->id);
4421 break;
4422 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004423 }
4424 }
4425 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004426 }
4427
Mingming Yin514a8bc2014-07-29 15:22:21 -07004428 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4429 if (ret >= 0) {
4430 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4431 adev->bt_wb_speech_enabled = true;
4432 else
4433 adev->bt_wb_speech_enabled = false;
4434 }
4435
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004436 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4437 if (ret >= 0) {
4438 val = atoi(value);
4439 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004440 ALOGV("cache new ext disp type and edid");
4441 ret = platform_get_ext_disp_type(adev->platform);
4442 if (ret < 0) {
4443 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004444 status = ret;
4445 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004446 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004447 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004448 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004449 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004450 /*
4451 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4452 * Per AudioPolicyManager, USB device is higher priority than WFD.
4453 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4454 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4455 * starting voice call on USB
4456 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004457 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4458 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004459 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4460 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004461 }
vivek mehta344576a2016-04-12 18:56:03 -07004462 ALOGV("detected USB connect .. disable proxy");
4463 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004464 }
4465 }
4466
4467 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4468 if (ret >= 0) {
4469 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004470 /*
4471 * The HDMI / Displayport disconnect handling has been moved to
4472 * audio extension to ensure that its parameters are not
4473 * invalidated prior to updating sysfs of the disconnect event
4474 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4475 */
4476 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004477 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004478 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4479 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304480 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4481 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004482 }
vivek mehta344576a2016-04-12 18:56:03 -07004483 ALOGV("detected USB disconnect .. enable proxy");
4484 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004485 }
4486 }
4487
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304488 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4489 if (ret >= 0) {
4490 struct audio_usecase *usecase;
4491 struct listnode *node;
4492 list_for_each(node, &adev->usecase_list) {
4493 usecase = node_to_item(node, struct audio_usecase, list);
4494 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004495 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304496 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304497 lock_output_stream(usecase->stream.out);
4498 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304499 //force device switch to re configure encoder
4500 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304501 audio_extn_a2dp_set_handoff_mode(false);
4502 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304503 break;
4504 }
4505 }
4506 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304507 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004508done:
4509 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004510 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304511error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004512 ALOGV("%s: exit with code(%d)", __func__, status);
4513 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514}
4515
4516static char* adev_get_parameters(const struct audio_hw_device *dev,
4517 const char *keys)
4518{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004519 struct audio_device *adev = (struct audio_device *)dev;
4520 struct str_parms *reply = str_parms_create();
4521 struct str_parms *query = str_parms_create_str(keys);
4522 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304523 char value[256] = {0};
4524 int ret = 0;
4525
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004526 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004527 if (reply) {
4528 str_parms_destroy(reply);
4529 }
4530 if (query) {
4531 str_parms_destroy(query);
4532 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004533 ALOGE("adev_get_parameters: failed to create query or reply");
4534 return NULL;
4535 }
4536
Naresh Tannirud7205b62014-06-20 02:54:48 +05304537 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4538 sizeof(value));
4539 if (ret >=0) {
4540 int val = 1;
4541 pthread_mutex_lock(&adev->snd_card_status.lock);
4542 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4543 val = 0;
4544 pthread_mutex_unlock(&adev->snd_card_status.lock);
4545 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4546 goto exit;
4547 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004548
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004549 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004550 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004551 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004552 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304553 pthread_mutex_unlock(&adev->lock);
4554
Naresh Tannirud7205b62014-06-20 02:54:48 +05304555exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004556 str = str_parms_to_str(reply);
4557 str_parms_destroy(query);
4558 str_parms_destroy(reply);
4559
4560 ALOGV("%s: exit: returns - %s", __func__, str);
4561 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562}
4563
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004564static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565{
4566 return 0;
4567}
4568
4569static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4570{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004571 int ret;
4572 struct audio_device *adev = (struct audio_device *)dev;
4573 pthread_mutex_lock(&adev->lock);
4574 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004575 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004576 pthread_mutex_unlock(&adev->lock);
4577 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578}
4579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004580static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4581 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582{
4583 return -ENOSYS;
4584}
4585
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004586static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4587 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588{
4589 return -ENOSYS;
4590}
4591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004592static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4593 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594{
4595 return -ENOSYS;
4596}
4597
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004598static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4599 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004600{
4601 return -ENOSYS;
4602}
4603
4604static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4605{
4606 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608 pthread_mutex_lock(&adev->lock);
4609 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004610 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004612 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004613 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004614 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004615 adev->current_call_output = NULL;
4616 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 }
4618 pthread_mutex_unlock(&adev->lock);
4619 return 0;
4620}
4621
4622static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4623{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004624 int ret;
4625
4626 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004627 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004628 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4629 pthread_mutex_unlock(&adev->lock);
4630
4631 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632}
4633
4634static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4635{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004636 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 return 0;
4638}
4639
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004640static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 const struct audio_config *config)
4642{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004643 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004645 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4646 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647}
4648
4649static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004650 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651 audio_devices_t devices,
4652 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004653 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304654 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004655 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004656 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657{
4658 struct audio_device *adev = (struct audio_device *)dev;
4659 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004660 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004661 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004662 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304663 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304666 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4667 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004668 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304669 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670
4671 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004672
4673 if (!in) {
4674 ALOGE("failed to allocate input stream");
4675 return -ENOMEM;
4676 }
4677
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304678 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304679 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4680 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004681 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004682 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684 in->stream.common.get_sample_rate = in_get_sample_rate;
4685 in->stream.common.set_sample_rate = in_set_sample_rate;
4686 in->stream.common.get_buffer_size = in_get_buffer_size;
4687 in->stream.common.get_channels = in_get_channels;
4688 in->stream.common.get_format = in_get_format;
4689 in->stream.common.set_format = in_set_format;
4690 in->stream.common.standby = in_standby;
4691 in->stream.common.dump = in_dump;
4692 in->stream.common.set_parameters = in_set_parameters;
4693 in->stream.common.get_parameters = in_get_parameters;
4694 in->stream.common.add_audio_effect = in_add_audio_effect;
4695 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4696 in->stream.set_gain = in_set_gain;
4697 in->stream.read = in_read;
4698 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4699
4700 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004701 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703 in->standby = 1;
4704 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004705 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004706 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304708 in->usecase = USECASE_AUDIO_RECORD;
4709 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4710 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4711 is_low_latency = true;
4712#if LOW_LATENCY_CAPTURE_USE_CASE
4713 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4714#endif
4715 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4716 }
4717
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004718 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004719 if (in->realtime) {
4720 in->config = pcm_config_audio_capture_rt;
4721 in->sample_rate = in->config.rate;
4722 in->af_period_multiplier = af_period_multiplier;
4723 } else {
4724 in->config = pcm_config_audio_capture;
4725 in->config.rate = config->sample_rate;
4726 in->sample_rate = config->sample_rate;
4727 in->af_period_multiplier = 1;
4728 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304729 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304731 /* restrict 24 bit capture for unprocessed source only
4732 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4733 */
4734 if (config->format == AUDIO_FORMAT_DEFAULT) {
4735 config->format = AUDIO_FORMAT_PCM_16_BIT;
4736 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4737 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4738 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4739 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4740 bool ret_error = false;
4741 in->bit_width = 24;
4742 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4743 from HAL is 24_packed and 8_24
4744 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4745 24_packed return error indicating supported format is 24_packed
4746 *> In case of any other source requesting 24 bit or float return error
4747 indicating format supported is 16 bit only.
4748
4749 on error flinger will retry with supported format passed
4750 */
4751 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4752 (source != AUDIO_SOURCE_CAMCORDER)) {
4753 config->format = AUDIO_FORMAT_PCM_16_BIT;
4754 if (config->sample_rate > 48000)
4755 config->sample_rate = 48000;
4756 ret_error = true;
4757 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4758 in->config.format = PCM_FORMAT_S24_3LE;
4759 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4760 in->config.format = PCM_FORMAT_S24_LE;
4761 } else {
4762 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4763 ret_error = true;
4764 }
4765
4766 if (ret_error) {
4767 ret = -EINVAL;
4768 goto err_open;
4769 }
4770 }
4771
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304772 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304773 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4774 (adev->mode != AUDIO_MODE_IN_CALL)) {
4775 ret = -EINVAL;
4776 goto err_open;
4777 }
4778
4779 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4780 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004781 if (config->sample_rate == 0)
4782 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4783 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4784 config->sample_rate != 8000) {
4785 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4786 ret = -EINVAL;
4787 goto err_open;
4788 }
4789 if (config->format == AUDIO_FORMAT_DEFAULT)
4790 config->format = AUDIO_FORMAT_PCM_16_BIT;
4791 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4792 config->format = AUDIO_FORMAT_PCM_16_BIT;
4793 ret = -EINVAL;
4794 goto err_open;
4795 }
4796
4797 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4798 in->config = pcm_config_afe_proxy_record;
4799 in->config.channels = channel_count;
4800 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304801 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304802 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4803 in, config, &channel_mask_updated)) {
4804 if (channel_mask_updated == true) {
4805 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4806 __func__, config->channel_mask);
4807 ret = -EINVAL;
4808 goto err_open;
4809 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304810 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004811 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004812 audio_extn_compr_cap_format_supported(config->format) &&
4813 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004814 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304815 } else if (audio_extn_cin_applicable_stream(in)) {
4816 ret = audio_extn_cin_configure_input_stream(in);
4817 if (ret)
4818 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004819 } else {
4820 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004821 if (!in->realtime) {
4822 in->format = config->format;
4823 frame_size = audio_stream_in_frame_size(&in->stream);
4824 buffer_size = get_input_buffer_size(config->sample_rate,
4825 config->format,
4826 channel_count,
4827 is_low_latency);
4828 in->config.period_size = buffer_size / frame_size;
4829 }
4830
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004831 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004832 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004833 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004834 (in->config.rate == 8000 || in->config.rate == 16000 ||
4835 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004836 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4837 voice_extn_compress_voip_open_input_stream(in);
4838 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304841 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4842 &adev->streams_input_cfg_list,
4843 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304844 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304845
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004846 /* This stream could be for sound trigger lab,
4847 get sound trigger pcm if present */
4848 audio_extn_sound_trigger_check_and_get_session(in);
4849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004851 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004852 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853
4854err_open:
4855 free(in);
4856 *stream_in = NULL;
4857 return ret;
4858}
4859
4860static void adev_close_input_stream(struct audio_hw_device *dev,
4861 struct audio_stream_in *stream)
4862{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004863 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004864 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004865 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304866
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304867 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004868
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304869 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004870 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304871
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004872 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304873 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004874 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304875 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004876 if (ret != 0)
4877 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4878 __func__, ret);
4879 } else
4880 in_standby(&stream->common);
4881
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004882 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004883 audio_extn_ssr_deinit();
4884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304886 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004887 audio_extn_compr_cap_format_supported(in->config.format))
4888 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304889
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304890 if (audio_extn_cin_attached_usecase(in->usecase))
4891 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004892
Mingming Yinfd7607b2016-01-22 12:48:44 -08004893 if (in->is_st_session) {
4894 ALOGV("%s: sound trigger pcm stop lab", __func__);
4895 audio_extn_sound_trigger_stop_lab(in);
4896 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004897 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898 return;
4899}
4900
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004901static int adev_dump(const audio_hw_device_t *device __unused,
4902 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903{
4904 return 0;
4905}
4906
4907static int adev_close(hw_device_t *device)
4908{
4909 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004910
4911 if (!adev)
4912 return 0;
4913
4914 pthread_mutex_lock(&adev_init_lock);
4915
4916 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004917 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004918 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304919 audio_extn_utils_release_streams_cfg_lists(
4920 &adev->streams_output_cfg_list,
4921 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304922 if (audio_extn_qaf_is_enabled())
4923 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004924 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004925 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004926 free(adev->snd_dev_ref_cnt);
4927 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004928 if (adev->adm_deinit)
4929 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304930 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004931 free(device);
4932 adev = NULL;
4933 }
4934 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004936 return 0;
4937}
4938
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004939/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4940 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4941 * just that it _might_ work.
4942 */
4943static int period_size_is_plausible_for_low_latency(int period_size)
4944{
4945 switch (period_size) {
4946 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004947 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004948 case 240:
4949 case 320:
4950 case 480:
4951 return 1;
4952 default:
4953 return 0;
4954 }
4955}
4956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957static int adev_open(const hw_module_t *module, const char *name,
4958 hw_device_t **device)
4959{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304960 int ret;
4961
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004962 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004963 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4964
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004965 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004966 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004967 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004968 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004969 ALOGD("%s: returning existing instance of adev", __func__);
4970 ALOGD("%s: exit", __func__);
4971 pthread_mutex_unlock(&adev_init_lock);
4972 return 0;
4973 }
4974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975 adev = calloc(1, sizeof(struct audio_device));
4976
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004977 if (!adev) {
4978 pthread_mutex_unlock(&adev_init_lock);
4979 return -ENOMEM;
4980 }
4981
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004982 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4985 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4986 adev->device.common.module = (struct hw_module_t *)module;
4987 adev->device.common.close = adev_close;
4988
4989 adev->device.init_check = adev_init_check;
4990 adev->device.set_voice_volume = adev_set_voice_volume;
4991 adev->device.set_master_volume = adev_set_master_volume;
4992 adev->device.get_master_volume = adev_get_master_volume;
4993 adev->device.set_master_mute = adev_set_master_mute;
4994 adev->device.get_master_mute = adev_get_master_mute;
4995 adev->device.set_mode = adev_set_mode;
4996 adev->device.set_mic_mute = adev_set_mic_mute;
4997 adev->device.get_mic_mute = adev_get_mic_mute;
4998 adev->device.set_parameters = adev_set_parameters;
4999 adev->device.get_parameters = adev_get_parameters;
5000 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5001 adev->device.open_output_stream = adev_open_output_stream;
5002 adev->device.close_output_stream = adev_close_output_stream;
5003 adev->device.open_input_stream = adev_open_input_stream;
5004 adev->device.close_input_stream = adev_close_input_stream;
5005 adev->device.dump = adev_dump;
5006
5007 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005009 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005010 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005013 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005014 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005015 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005016 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005017 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005018 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005019 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005020 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305021 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305022 adev->perf_lock_opts[0] = 0x101;
5023 adev->perf_lock_opts[1] = 0x20E;
5024 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305025
5026 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5027 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005029 adev->platform = platform_init(adev);
5030 if (!adev->platform) {
5031 free(adev->snd_dev_ref_cnt);
5032 free(adev);
5033 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5034 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005035 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305036 pthread_mutex_destroy(&adev->lock);
5037 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005038 return -EINVAL;
5039 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005040
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305041 if (audio_extn_qaf_is_enabled()) {
5042 ret = audio_extn_qaf_init(adev);
5043 if (ret < 0) {
5044 free(adev);
5045 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5046 *device = NULL;
5047 pthread_mutex_unlock(&adev_init_lock);
5048 pthread_mutex_destroy(&adev->lock);
5049 return ret;
5050 }
5051
5052 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5053 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5054 }
5055
Naresh Tanniru4c630392014-05-12 01:05:52 +05305056 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5057
Eric Laurentc4aef752013-09-12 17:45:53 -07005058 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5059 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5060 if (adev->visualizer_lib == NULL) {
5061 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5062 } else {
5063 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5064 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005065 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005066 "visualizer_hal_start_output");
5067 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005068 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005069 "visualizer_hal_stop_output");
5070 }
5071 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305072 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005073 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005074 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005075 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005076
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005077 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5078 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5079 if (adev->offload_effects_lib == NULL) {
5080 ALOGE("%s: DLOPEN failed for %s", __func__,
5081 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5082 } else {
5083 ALOGV("%s: DLOPEN successful for %s", __func__,
5084 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5085 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305086 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005087 "offload_effects_bundle_hal_start_output");
5088 adev->offload_effects_stop_output =
5089 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5090 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005091 adev->offload_effects_set_hpx_state =
5092 (int (*)(bool))dlsym(adev->offload_effects_lib,
5093 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305094 adev->offload_effects_get_parameters =
5095 (void (*)(struct str_parms *, struct str_parms *))
5096 dlsym(adev->offload_effects_lib,
5097 "offload_effects_bundle_get_parameters");
5098 adev->offload_effects_set_parameters =
5099 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5100 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005101 }
5102 }
5103
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005104 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5105 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5106 if (adev->adm_lib == NULL) {
5107 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5108 } else {
5109 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5110 adev->adm_init = (adm_init_t)
5111 dlsym(adev->adm_lib, "adm_init");
5112 adev->adm_deinit = (adm_deinit_t)
5113 dlsym(adev->adm_lib, "adm_deinit");
5114 adev->adm_register_input_stream = (adm_register_input_stream_t)
5115 dlsym(adev->adm_lib, "adm_register_input_stream");
5116 adev->adm_register_output_stream = (adm_register_output_stream_t)
5117 dlsym(adev->adm_lib, "adm_register_output_stream");
5118 adev->adm_deregister_stream = (adm_deregister_stream_t)
5119 dlsym(adev->adm_lib, "adm_deregister_stream");
5120 adev->adm_request_focus = (adm_request_focus_t)
5121 dlsym(adev->adm_lib, "adm_request_focus");
5122 adev->adm_abandon_focus = (adm_abandon_focus_t)
5123 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005124 adev->adm_set_config = (adm_set_config_t)
5125 dlsym(adev->adm_lib, "adm_set_config");
5126 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5127 dlsym(adev->adm_lib, "adm_request_focus_v2");
5128 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5129 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5130 adev->adm_on_routing_change = (adm_on_routing_change_t)
5131 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005132 }
5133 }
5134
Mingming Yin514a8bc2014-07-29 15:22:21 -07005135 adev->bt_wb_speech_enabled = false;
5136
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005137 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005138 *device = &adev->device.common;
5139
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305140 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5141 &adev->streams_output_cfg_list,
5142 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005143
Kiran Kandi910e1862013-10-29 13:29:42 -07005144 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005145
5146 char value[PROPERTY_VALUE_MAX];
5147 int trial;
5148 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5149 trial = atoi(value);
5150 if (period_size_is_plausible_for_low_latency(trial)) {
5151 pcm_config_low_latency.period_size = trial;
5152 pcm_config_low_latency.start_threshold = trial / 4;
5153 pcm_config_low_latency.avail_min = trial / 4;
5154 configured_low_latency_capture_period_size = trial;
5155 }
5156 }
5157 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5158 trial = atoi(value);
5159 if (period_size_is_plausible_for_low_latency(trial)) {
5160 configured_low_latency_capture_period_size = trial;
5161 }
5162 }
5163
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005164 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5165 af_period_multiplier = atoi(value);
5166 if (af_period_multiplier < 0)
5167 af_period_multiplier = 2;
5168 else if (af_period_multiplier > 4)
5169 af_period_multiplier = 4;
5170
5171 ALOGV("new period_multiplier = %d", af_period_multiplier);
5172 }
5173
vivek mehta446c3962015-09-14 10:57:35 -07005174 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005175 pthread_mutex_unlock(&adev_init_lock);
5176
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005177 if (adev->adm_init)
5178 adev->adm_data = adev->adm_init();
5179
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305180 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305181 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005182 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005183 return 0;
5184}
5185
5186static struct hw_module_methods_t hal_module_methods = {
5187 .open = adev_open,
5188};
5189
5190struct audio_module HAL_MODULE_INFO_SYM = {
5191 .common = {
5192 .tag = HARDWARE_MODULE_TAG,
5193 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5194 .hal_api_version = HARDWARE_HAL_API_VERSION,
5195 .id = AUDIO_HARDWARE_MODULE_ID,
5196 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005197 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198 .methods = &hal_module_methods,
5199 },
5200};