blob: b3a985c839ea2eb330c3838f6419b47a694886f4 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
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 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530506 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
507 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530508 format == AUDIO_FORMAT_PCM_FLOAT ||
509 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700510 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530511 format == AUDIO_FORMAT_AC3 ||
512 format == AUDIO_FORMAT_E_AC3 ||
513 format == AUDIO_FORMAT_DTS ||
514 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800515 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530516 format == AUDIO_FORMAT_ALAC ||
517 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530518 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800520 format == AUDIO_FORMAT_WMA ||
521 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800522 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523
524 return false;
525}
526
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700527static inline bool is_mmap_usecase(audio_usecase_t uc_id)
528{
529 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
530 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
531}
532
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530533int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530534{
535 int snd_scard_state;
536
537 if (!adev)
538 return SND_CARD_STATE_OFFLINE;
539
540 pthread_mutex_lock(&adev->snd_card_status.lock);
541 snd_scard_state = adev->snd_card_status.state;
542 pthread_mutex_unlock(&adev->snd_card_status.lock);
543
544 return snd_scard_state;
545}
546
547static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
548{
549 if (!adev)
550 return -ENOSYS;
551
552 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700553 if (adev->snd_card_status.state != snd_scard_state) {
554 adev->snd_card_status.state = snd_scard_state;
555 platform_snd_card_update(adev->platform, snd_scard_state);
556 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530557 pthread_mutex_unlock(&adev->snd_card_status.lock);
558
559 return 0;
560}
561
Avinash Vaish71a8b972014-07-24 15:36:33 +0530562static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
563 struct audio_usecase *uc_info)
564{
565 struct listnode *node;
566 struct audio_usecase *usecase;
567
568 if (uc_info == NULL)
569 return -EINVAL;
570
571 /* Re-route all voice usecases on the shared backend other than the
572 specified usecase to new snd devices */
573 list_for_each(node, &adev->usecase_list) {
574 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800575 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530576 enable_audio_route(adev, usecase);
577 }
578 return 0;
579}
580
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530581static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530582{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530583 ALOGV("%s", __func__);
584 audio_route_apply_and_update_path(adev->audio_route,
585 "asrc-mode");
586 adev->asrc_mode_enabled = true;
587}
588
589static void disable_asrc_mode(struct audio_device *adev)
590{
591 ALOGV("%s", __func__);
592 audio_route_reset_and_update_path(adev->audio_route,
593 "asrc-mode");
594 adev->asrc_mode_enabled = false;
595}
596
597/*
598 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
599 * 44.1 or Native DSD backends are enabled for any of current use case.
600 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
601 * - Disable current mix path use case(Headphone backend) and re-enable it with
602 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
603 * e.g. Naitve DSD or Headphone 44.1 -> + 48
604 */
605static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
606{
607 ALOGV("%s snd device %d", __func__, snd_device);
608 int new_backend_idx = platform_get_backend_index(snd_device);
609
610 if (((new_backend_idx == HEADPHONE_BACKEND) ||
611 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
612 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
613 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530614 struct listnode *node = NULL;
615 struct audio_usecase *uc = NULL;
616 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530617 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618
619 list_for_each(node, &adev->usecase_list) {
620 uc = node_to_item(node, struct audio_usecase, list);
621 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530622 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530623 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
624
625 if((new_backend_idx == HEADPHONE_BACKEND) &&
626 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
627 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530628 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
629 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530630 enable_asrc_mode(adev);
631 break;
632 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
633 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
634 (usecase_backend_idx == HEADPHONE_BACKEND)) {
635 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
636 __func__);
637 disable_audio_route(adev, uc);
638 disable_snd_device(adev, uc->out_snd_device);
639 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
640 if (new_backend_idx == DSD_NATIVE_BACKEND)
641 audio_route_apply_and_update_path(adev->audio_route,
642 "hph-true-highquality-mode");
643 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
644 (curr_out->bit_width >= 24))
645 audio_route_apply_and_update_path(adev->audio_route,
646 "hph-highquality-mode");
647 enable_asrc_mode(adev);
648 enable_snd_device(adev, uc->out_snd_device);
649 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530650 break;
651 }
652 }
653 }
654 }
655}
656
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700657int pcm_ioctl(struct pcm *pcm, int request, ...)
658{
659 va_list ap;
660 void * arg;
661 int pcm_fd = *(int*)pcm;
662
663 va_start(ap, request);
664 arg = va_arg(ap, void *);
665 va_end(ap);
666
667 return ioctl(pcm_fd, request, arg);
668}
669
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700670int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700671 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700674 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800675
676 if (usecase == NULL)
677 return -EINVAL;
678
679 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
680
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800683 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800685
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800686#ifdef DS1_DOLBY_DAP_ENABLED
687 audio_extn_dolby_set_dmid(adev);
688 audio_extn_dolby_set_endpoint(adev);
689#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700690 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700691 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530692 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700693 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530694 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800695 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700696 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700697 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700698 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699 ALOGV("%s: exit", __func__);
700 return 0;
701}
702
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700703int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700704 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700707 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530709 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800710 return -EINVAL;
711
712 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 if (usecase->type == PCM_CAPTURE)
714 snd_device = usecase->in_snd_device;
715 else
716 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800717 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700718 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700719 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700720 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700721 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530722 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723 ALOGV("%s: exit", __func__);
724 return 0;
725}
726
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700727int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700728 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800729{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530730 int i, num_devices = 0;
731 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700732 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
733
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800734 if (snd_device < SND_DEVICE_MIN ||
735 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800736 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800737 return -EINVAL;
738 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739
740 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700741
742 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
743 ALOGE("%s: Invalid sound device returned", __func__);
744 return -EINVAL;
745 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700747 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700748 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 return 0;
750 }
751
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530752
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700753 if (audio_extn_spkr_prot_is_enabled())
754 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700755
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800756 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
757 audio_extn_spkr_prot_is_enabled()) {
758 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700759 adev->snd_dev_ref_cnt[snd_device]--;
760 return -EINVAL;
761 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200762 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800763 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800764 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200765 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800766 return -EINVAL;
767 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700768 } else if (platform_split_snd_device(adev->platform,
769 snd_device,
770 &num_devices,
771 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530772 for (i = 0; i < num_devices; i++) {
773 enable_snd_device(adev, new_snd_devices[i]);
774 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800775 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530777
778 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
779 (audio_extn_a2dp_start_playback() < 0)) {
780 ALOGE(" fail to configure A2dp control path ");
781 return -EINVAL;
782 }
783
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700784 /* due to the possibility of calibration overwrite between listen
785 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700786 audio_extn_sound_trigger_update_device_status(snd_device,
787 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530788 audio_extn_listen_update_device_status(snd_device,
789 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700791 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700792 audio_extn_sound_trigger_update_device_status(snd_device,
793 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530794 audio_extn_listen_update_device_status(snd_device,
795 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700796 return -EINVAL;
797 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300798 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700799 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530800
801 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
802 !adev->native_playback_enabled &&
803 audio_is_true_native_stream_active(adev)) {
804 ALOGD("%s: %d: napb: enabling native mode in hardware",
805 __func__, __LINE__);
806 audio_route_apply_and_update_path(adev->audio_route,
807 "true-native-mode");
808 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800811 return 0;
812}
813
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700814int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700815 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530817 int i, num_devices = 0;
818 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700819 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
820
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 if (snd_device < SND_DEVICE_MIN ||
822 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800823 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800824 return -EINVAL;
825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
827 ALOGE("%s: device ref cnt is already 0", __func__);
828 return -EINVAL;
829 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700832
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700833 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
834 ALOGE("%s: Invalid sound device returned", __func__);
835 return -EINVAL;
836 }
837
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700839 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530840
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800841 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
842 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700843 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700844 } else if (platform_split_snd_device(adev->platform,
845 snd_device,
846 &num_devices,
847 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530848 for (i = 0; i < num_devices; i++) {
849 disable_snd_device(adev, new_snd_devices[i]);
850 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300851 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700852 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300853 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700854
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530855 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
856 audio_extn_a2dp_stop_playback();
857
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700858 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530859 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530860 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
861 adev->native_playback_enabled) {
862 ALOGD("%s: %d: napb: disabling native mode in hardware",
863 __func__, __LINE__);
864 audio_route_reset_and_update_path(adev->audio_route,
865 "true-native-mode");
866 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530867 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
868 adev->asrc_mode_enabled) {
869 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530870 disable_asrc_mode(adev);
871 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530872 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530873
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200874 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700875 audio_extn_sound_trigger_update_device_status(snd_device,
876 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530877 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800878 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 return 0;
882}
883
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700884/*
885 legend:
886 uc - existing usecase
887 new_uc - new usecase
888 d1, d11, d2 - SND_DEVICE enums
889 a1, a2 - corresponding ANDROID device enums
890 B1, B2 - backend strings
891
892case 1
893 uc->dev d1 (a1) B1
894 new_uc->dev d1 (a1), d2 (a2) B1, B2
895
896 resolution: disable and enable uc->dev on d1
897
898case 2
899 uc->dev d1 (a1) B1
900 new_uc->dev d11 (a1) B1
901
902 resolution: need to switch uc since d1 and d11 are related
903 (e.g. speaker and voice-speaker)
904 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
905
906case 3
907 uc->dev d1 (a1) B1
908 new_uc->dev d2 (a2) B2
909
910 resolution: no need to switch uc
911
912case 4
913 uc->dev d1 (a1) B1
914 new_uc->dev d2 (a2) B1
915
916 resolution: disable enable uc-dev on d2 since backends match
917 we cannot enable two streams on two different devices if they
918 share the same backend. e.g. if offload is on speaker device using
919 QUAD_MI2S backend and a low-latency stream is started on voice-handset
920 using the same backend, offload must also be switched to voice-handset.
921
922case 5
923 uc->dev d1 (a1) B1
924 new_uc->dev d1 (a1), d2 (a2) B1
925
926 resolution: disable enable uc-dev on d2 since backends match
927 we cannot enable two streams on two different devices if they
928 share the same backend.
929
930case 6
931 uc->dev d1 (a1) B1
932 new_uc->dev d2 (a1) B2
933
934 resolution: no need to switch
935
936case 7
937 uc->dev d1 (a1), d2 (a2) B1, B2
938 new_uc->dev d1 (a1) B1
939
940 resolution: no need to switch
941
942*/
943static snd_device_t derive_playback_snd_device(void * platform,
944 struct audio_usecase *uc,
945 struct audio_usecase *new_uc,
946 snd_device_t new_snd_device)
947{
948 audio_devices_t a1 = uc->stream.out->devices;
949 audio_devices_t a2 = new_uc->stream.out->devices;
950
951 snd_device_t d1 = uc->out_snd_device;
952 snd_device_t d2 = new_snd_device;
953
954 // Treat as a special case when a1 and a2 are not disjoint
955 if ((a1 != a2) && (a1 & a2)) {
956 snd_device_t d3[2];
957 int num_devices = 0;
958 int ret = platform_split_snd_device(platform,
959 popcount(a1) > 1 ? d1 : d2,
960 &num_devices,
961 d3);
962 if (ret < 0) {
963 if (ret != -ENOSYS) {
964 ALOGW("%s failed to split snd_device %d",
965 __func__,
966 popcount(a1) > 1 ? d1 : d2);
967 }
968 goto end;
969 }
970
971 // NB: case 7 is hypothetical and isn't a practical usecase yet.
972 // But if it does happen, we need to give priority to d2 if
973 // the combo devices active on the existing usecase share a backend.
974 // This is because we cannot have a usecase active on a combo device
975 // and a new usecase requests one device in this combo pair.
976 if (platform_check_backends_match(d3[0], d3[1])) {
977 return d2; // case 5
978 } else {
979 return d1; // case 1
980 }
981 } else {
982 if (platform_check_backends_match(d1, d2)) {
983 return d2; // case 2, 4
984 } else {
985 return d1; // case 6, 3
986 }
987 }
988
989end:
990 return d2; // return whatever was calculated before.
991}
992
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530994 struct audio_usecase *uc_info,
995 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700996{
997 struct listnode *node;
998 struct audio_usecase *usecase;
999 bool switch_device[AUDIO_USECASE_MAX];
1000 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301001 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001002 /*
1003 * This function is to make sure that all the usecases that are active on
1004 * the hardware codec backend are always routed to any one device that is
1005 * handled by the hardware codec.
1006 * For example, if low-latency and deep-buffer usecases are currently active
1007 * on speaker and out_set_parameters(headset) is received on low-latency
1008 * output, then we have to make sure deep-buffer is also switched to headset,
1009 * because of the limitation that both the devices cannot be enabled
1010 * at the same time as they share the same backend.
1011 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001012 /*
1013 * This call is to check if we need to force routing for a particular stream
1014 * If there is a backend configuration change for the device when a
1015 * new stream starts, then ADM needs to be closed and re-opened with the new
1016 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001017 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001018 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001019 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1020 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301021 /* For a2dp device reconfigure all active sessions
1022 * with new AFE encoder format based on a2dp state
1023 */
1024 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1025 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1026 audio_extn_a2dp_is_force_device_switch()) {
1027 force_routing = true;
1028 force_restart_session = true;
1029 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301030 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1031
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001033 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001034 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1036 switch_device[i] = false;
1037
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001040
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301041 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1042 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301043 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301044 platform_get_snd_device_name(usecase->out_snd_device),
1045 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001046 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301047 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001048 (derive_playback_snd_device(adev->platform,
1049 usecase, uc_info,
1050 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301051 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1052 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301053 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301054 (force_restart_session)) &&
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301055 (platform_check_backends_match(snd_device, usecase->out_snd_device))) {
1056
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301057 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1058 __func__, use_case_table[usecase->id],
1059 platform_get_snd_device_name(usecase->out_snd_device));
1060 disable_audio_route(adev, usecase);
1061 switch_device[usecase->id] = true;
1062 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001063 }
1064 }
1065
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301066 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1067 num_uc_to_switch);
1068
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001070 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301072 /* Make sure the previous devices to be disabled first and then enable the
1073 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 list_for_each(node, &adev->usecase_list) {
1075 usecase = node_to_item(node, struct audio_usecase, list);
1076 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001077 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 }
1079 }
1080
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001081 list_for_each(node, &adev->usecase_list) {
1082 usecase = node_to_item(node, struct audio_usecase, list);
1083 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001084 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001085 }
1086 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 /* Re-route all the usecases on the shared backend other than the
1089 specified usecase to new snd devices */
1090 list_for_each(node, &adev->usecase_list) {
1091 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301092 /* Update the out_snd_device only before enabling the audio route */
1093 if (switch_device[usecase->id]) {
1094 usecase->out_snd_device = snd_device;
1095 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301096 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301097 use_case_table[usecase->id],
1098 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301099 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301100 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 }
1102 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 }
1104}
1105
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301106static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001107 struct audio_usecase *uc_info,
1108 snd_device_t snd_device)
1109{
1110 struct listnode *node;
1111 struct audio_usecase *usecase;
1112 bool switch_device[AUDIO_USECASE_MAX];
1113 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301114 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001115
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301116 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1117 snd_device);
1118 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301119
1120 /*
1121 * Make sure out devices is checked against out codec backend device and
1122 * also in devices against in codec backend. Checking out device against in
1123 * codec backend or vice versa causes issues.
1124 */
1125 if (uc_info->type == PCM_CAPTURE)
1126 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001127 /*
1128 * This function is to make sure that all the active capture usecases
1129 * are always routed to the same input sound device.
1130 * For example, if audio-record and voice-call usecases are currently
1131 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1132 * is received for voice call then we have to make sure that audio-record
1133 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1134 * because of the limitation that two devices cannot be enabled
1135 * at the same time if they share the same backend.
1136 */
1137 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1138 switch_device[i] = false;
1139
1140 list_for_each(node, &adev->usecase_list) {
1141 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301142 /*
1143 * TODO: Enhance below condition to handle BT sco/USB multi recording
1144 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001145 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001146 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301147 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301148 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301149 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001150 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001151 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001152 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1153 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001154 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001155 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001156 switch_device[usecase->id] = true;
1157 num_uc_to_switch++;
1158 }
1159 }
1160
1161 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001162 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001163
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301164 /* Make sure the previous devices to be disabled first and then enable the
1165 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001166 list_for_each(node, &adev->usecase_list) {
1167 usecase = node_to_item(node, struct audio_usecase, list);
1168 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001169 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001170 }
1171 }
1172
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
1175 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001176 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001177 }
1178 }
1179
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001180 /* Re-route all the usecases on the shared backend other than the
1181 specified usecase to new snd devices */
1182 list_for_each(node, &adev->usecase_list) {
1183 usecase = node_to_item(node, struct audio_usecase, list);
1184 /* Update the in_snd_device only before enabling the audio route */
1185 if (switch_device[usecase->id] ) {
1186 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001187 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301188 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001189 }
1190 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 }
1192}
1193
Mingming Yin3a941d42016-02-17 18:08:05 -08001194static void reset_hdmi_sink_caps(struct stream_out *out) {
1195 int i = 0;
1196
1197 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1198 out->supported_channel_masks[i] = 0;
1199 }
1200 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1201 out->supported_formats[i] = 0;
1202 }
1203 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1204 out->supported_sample_rates[i] = 0;
1205 }
1206}
1207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001209static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210{
Mingming Yin3a941d42016-02-17 18:08:05 -08001211 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001212 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001213
Mingming Yin3a941d42016-02-17 18:08:05 -08001214 reset_hdmi_sink_caps(out);
1215
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001216 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001217 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001218 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001219 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001220 }
1221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001224 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001225 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001226 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1227 case 6:
1228 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1229 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1230 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1231 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1232 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1233 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234 break;
1235 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001236 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001237 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001238 break;
1239 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001240
1241 // check channel format caps
1242 i = 0;
1243 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1244 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1245 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1246 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1247 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1248 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1249 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1250 }
1251
1252 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1253 ALOGV(":%s HDMI supports DTS format", __func__);
1254 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1255 }
1256
1257 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1258 ALOGV(":%s HDMI supports DTS HD format", __func__);
1259 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1260 }
1261
1262
1263 // check sample rate caps
1264 i = 0;
1265 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1266 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1267 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1268 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1269 }
1270 }
1271
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001272 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273}
1274
Alexy Josephb1379942016-01-29 15:49:38 -08001275audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001276 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001277{
1278 struct audio_usecase *usecase;
1279 struct listnode *node;
1280
1281 list_for_each(node, &adev->usecase_list) {
1282 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001283 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001284 ALOGV("%s: usecase id %d", __func__, usecase->id);
1285 return usecase->id;
1286 }
1287 }
1288 return USECASE_INVALID;
1289}
1290
Alexy Josephb1379942016-01-29 15:49:38 -08001291struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001292 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293{
1294 struct audio_usecase *usecase;
1295 struct listnode *node;
1296
1297 list_for_each(node, &adev->usecase_list) {
1298 usecase = node_to_item(node, struct audio_usecase, list);
1299 if (usecase->id == uc_id)
1300 return usecase;
1301 }
1302 return NULL;
1303}
1304
Dhananjay Kumard4833242016-10-06 22:09:12 +05301305struct stream_in *get_next_active_input(const struct audio_device *adev)
1306{
1307 struct audio_usecase *usecase;
1308 struct listnode *node;
1309
1310 list_for_each_reverse(node, &adev->usecase_list) {
1311 usecase = node_to_item(node, struct audio_usecase, list);
1312 if (usecase->type == PCM_CAPTURE)
1313 return usecase->stream.in;
1314 }
1315 return NULL;
1316}
1317
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301318/*
1319 * is a true native playback active
1320 */
1321bool audio_is_true_native_stream_active(struct audio_device *adev)
1322{
1323 bool active = false;
1324 int i = 0;
1325 struct listnode *node;
1326
1327 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1328 ALOGV("%s:napb: not in true mode or non hdphones device",
1329 __func__);
1330 active = false;
1331 goto exit;
1332 }
1333
1334 list_for_each(node, &adev->usecase_list) {
1335 struct audio_usecase *uc;
1336 uc = node_to_item(node, struct audio_usecase, list);
1337 struct stream_out *curr_out =
1338 (struct stream_out*) uc->stream.out;
1339
1340 if (curr_out && PCM_PLAYBACK == uc->type) {
1341 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1342 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1343 uc->id, curr_out->sample_rate,
1344 curr_out->bit_width,
1345 platform_get_snd_device_name(uc->out_snd_device));
1346
1347 if (is_offload_usecase(uc->id) &&
1348 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1349 active = true;
1350 ALOGD("%s:napb:native stream detected", __func__);
1351 }
1352 }
1353 }
1354exit:
1355 return active;
1356}
1357
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301358/*
1359 * if native DSD playback active
1360 */
1361bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1362{
1363 bool active = false;
1364 struct listnode *node = NULL;
1365 struct audio_usecase *uc = NULL;
1366 struct stream_out *curr_out = NULL;
1367
1368 list_for_each(node, &adev->usecase_list) {
1369 uc = node_to_item(node, struct audio_usecase, list);
1370 curr_out = (struct stream_out*) uc->stream.out;
1371
1372 if (curr_out && PCM_PLAYBACK == uc->type &&
1373 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1374 active = true;
1375 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301376 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301377 }
1378 }
1379 return active;
1380}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301381
1382static bool force_device_switch(struct audio_usecase *usecase)
1383{
1384 bool ret = false;
1385 bool is_it_true_mode = false;
1386
1387 if (is_offload_usecase(usecase->id) &&
1388 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001389 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1390 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1391 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301392 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1393 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1394 (!is_it_true_mode && adev->native_playback_enabled)){
1395 ret = true;
1396 ALOGD("napb: time to toggle native mode");
1397 }
1398 }
1399
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301400 // Force all a2dp output devices to reconfigure for proper AFE encode format
1401 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001402 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301403 audio_extn_a2dp_is_force_device_switch()) {
1404 ALOGD("Force a2dp device switch to update new encoder config");
1405 ret = true;
1406 }
1407
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301408 return ret;
1409}
1410
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001411int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001413 snd_device_t out_snd_device = SND_DEVICE_NONE;
1414 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001415 struct audio_usecase *usecase = NULL;
1416 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001417 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001418 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001419 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001420 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301422 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1423
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424 usecase = get_usecase_from_list(adev, uc_id);
1425 if (usecase == NULL) {
1426 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1427 return -EINVAL;
1428 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001430 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001431 (usecase->type == VOIP_CALL) ||
1432 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301433 if(usecase->stream.out == NULL) {
1434 ALOGE("%s: stream.out is NULL", __func__);
1435 return -EINVAL;
1436 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001437 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001438 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001439 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 usecase->devices = usecase->stream.out->devices;
1441 } else {
1442 /*
1443 * If the voice call is active, use the sound devices of voice call usecase
1444 * so that it would not result any device switch. All the usecases will
1445 * be switched to new device when select_devices() is called for voice call
1446 * usecase. This is to avoid switching devices for voice call when
1447 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001448 * choose voice call device only if the use case device is
1449 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001450 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001451 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001452 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001453 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001454 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1455 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301456 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1457 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001458 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001459 in_snd_device = vc_usecase->in_snd_device;
1460 out_snd_device = vc_usecase->out_snd_device;
1461 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001462 } else if (voice_extn_compress_voip_is_active(adev)) {
1463 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001464 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001465 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1466 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001467 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001468 in_snd_device = voip_usecase->in_snd_device;
1469 out_snd_device = voip_usecase->out_snd_device;
1470 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001471 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001472 hfp_ucid = audio_extn_hfp_get_usecase();
1473 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001474 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001475 in_snd_device = hfp_usecase->in_snd_device;
1476 out_snd_device = hfp_usecase->out_snd_device;
1477 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 }
1479 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301480 if (usecase->stream.out == NULL) {
1481 ALOGE("%s: stream.out is NULL", __func__);
1482 return -EINVAL;
1483 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001484 usecase->devices = usecase->stream.out->devices;
1485 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001486 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001487 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001488 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001489 if (usecase->stream.out == adev->primary_output &&
1490 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001491 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001492 select_devices(adev, adev->active_input->usecase);
1493 }
1494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301496 if (usecase->stream.in == NULL) {
1497 ALOGE("%s: stream.in is NULL", __func__);
1498 return -EINVAL;
1499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 usecase->devices = usecase->stream.in->device;
1501 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001502 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001503 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001504 if (adev->active_input &&
1505 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301506 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1507 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1508 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001509 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001510 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001511 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1512 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001513 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001514 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001515 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 }
1517 }
1518
1519 if (out_snd_device == usecase->out_snd_device &&
1520 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301521
1522 if (!force_device_switch(usecase))
1523 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 }
1525
sangwoobc677242013-08-08 16:53:43 +09001526 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001527 out_snd_device, platform_get_snd_device_name(out_snd_device),
1528 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 /*
1531 * Limitation: While in call, to do a device switch we need to disable
1532 * and enable both RX and TX devices though one of them is same as current
1533 * device.
1534 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001535 if ((usecase->type == VOICE_CALL) &&
1536 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1537 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001538 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001539 }
1540
1541 if (((usecase->type == VOICE_CALL) ||
1542 (usecase->type == VOIP_CALL)) &&
1543 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1544 /* Disable sidetone only if voice/voip call already exists */
1545 if (voice_is_call_state_active(adev) ||
1546 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001547 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001548
1549 /* Disable aanc only if voice call exists */
1550 if (voice_is_call_state_active(adev))
1551 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001552 }
1553
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 /* Disable current sound devices */
1555 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001556 disable_audio_route(adev, usecase);
1557 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558 }
1559
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001561 disable_audio_route(adev, usecase);
1562 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 }
1564
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001565 /* Applicable only on the targets that has external modem.
1566 * New device information should be sent to modem before enabling
1567 * the devices to reduce in-call device switch time.
1568 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001569 if ((usecase->type == VOICE_CALL) &&
1570 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1571 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001572 status = platform_switch_voice_call_enable_device_config(adev->platform,
1573 out_snd_device,
1574 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001575 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 /* Enable new sound devices */
1578 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001579 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301580 if (platform_check_codec_asrc_support(adev->platform))
1581 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001582 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 }
1584
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001585 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301586 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001587 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001588 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589
Avinash Vaish71a8b972014-07-24 15:36:33 +05301590 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001591 status = platform_switch_voice_call_device_post(adev->platform,
1592 out_snd_device,
1593 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301594 enable_audio_route_for_voice_usecases(adev, usecase);
1595 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001596
sangwoo170731f2013-06-08 15:36:36 +09001597 usecase->in_snd_device = in_snd_device;
1598 usecase->out_snd_device = out_snd_device;
1599
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301600 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1601 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301602 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001603 if ((24 == usecase->stream.out->bit_width) &&
1604 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1605 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1606 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1607 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1608 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1609 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1610 /*
1611 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1612 * configured device sample rate, if not update the COPP rate to be equal to the
1613 * device sample rate, else open COPP at stream sample rate
1614 */
1615 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1616 usecase->stream.out->sample_rate,
1617 &usecase->stream.out->app_type_cfg.sample_rate);
1618 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1619 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1620 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1621 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1622 }
1623
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001624 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001625 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001626 audio_extn_gef_notify_device_config(
1627 usecase->stream.out->devices,
1628 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001629 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001630 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001631 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301632 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001633 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001634
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001635 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001636 /* Enable aanc only if voice call exists */
1637 if (voice_is_call_state_active(adev))
1638 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1639
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001640 /* Enable sidetone only if other voice/voip call already exists */
1641 if (voice_is_call_state_active(adev) ||
1642 voice_extn_compress_voip_is_started(adev))
1643 voice_set_sidetone(adev, out_snd_device, true);
1644 }
1645
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001646 /* Applicable only on the targets that has external modem.
1647 * Enable device command should be sent to modem only after
1648 * enabling voice call mixer controls
1649 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001650 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001651 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1652 out_snd_device,
1653 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301654 ALOGD("%s: done",__func__);
1655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 return status;
1657}
1658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659static int stop_input_stream(struct stream_in *in)
1660{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301661 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 struct audio_usecase *uc_info;
1663 struct audio_device *adev = in->dev;
1664
Dhananjay Kumard4833242016-10-06 22:09:12 +05301665 adev->active_input = get_next_active_input(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666
Eric Laurent994a6932013-07-17 11:51:42 -07001667 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 uc_info = get_usecase_from_list(adev, in->usecase);
1670 if (uc_info == NULL) {
1671 ALOGE("%s: Could not find the usecase (%d) in the list",
1672 __func__, in->usecase);
1673 return -EINVAL;
1674 }
1675
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001676 /* Close in-call recording streams */
1677 voice_check_and_stop_incall_rec_usecase(adev, in);
1678
Eric Laurent150dbfe2013-02-27 14:31:02 -08001679 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001680 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001681
1682 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001683 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001685 list_remove(&uc_info->list);
1686 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687
Eric Laurent994a6932013-07-17 11:51:42 -07001688 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 return ret;
1690}
1691
1692int start_input_stream(struct stream_in *in)
1693{
1694 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001695 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 struct audio_usecase *uc_info;
1697 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301698 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699
Mingming Yin2664a5b2015-09-03 10:53:11 -07001700 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1701 if (get_usecase_from_list(adev, usecase) == NULL)
1702 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301703 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1704 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001705
Naresh Tanniru80659832014-06-04 18:17:56 +05301706
1707 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301708 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301709 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301710 goto error_config;
1711 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301712
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001713 /* Check if source matches incall recording usecase criteria */
1714 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1715 if (ret)
1716 goto error_config;
1717 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001718 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1719
1720 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1721 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1722 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001723 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001724 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001725
Eric Laurentb23d5282013-05-14 15:27:20 -07001726 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 if (in->pcm_device_id < 0) {
1728 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1729 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001730 ret = -EINVAL;
1731 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001733
1734 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001736
1737 if (!uc_info) {
1738 ret = -ENOMEM;
1739 goto error_config;
1740 }
1741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 uc_info->id = in->usecase;
1743 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001744 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 uc_info->devices = in->device;
1746 uc_info->in_snd_device = SND_DEVICE_NONE;
1747 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001749 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301750 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1751 adev->perf_lock_opts,
1752 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301755 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1756 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001757
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301758 if (audio_extn_cin_attached_usecase(in->usecase)) {
1759 ret = audio_extn_cin_start_input_stream(in);
1760 if (ret)
1761 goto error_open;
1762 else
1763 goto done_open;
1764 }
1765
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001766 unsigned int flags = PCM_IN;
1767 unsigned int pcm_open_retry_count = 0;
1768
1769 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1770 flags |= PCM_MMAP | PCM_NOIRQ;
1771 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001772 } else if (in->realtime) {
1773 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001774 }
1775
1776 while (1) {
1777 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1778 flags, &in->config);
1779 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1780 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1781 if (in->pcm != NULL) {
1782 pcm_close(in->pcm);
1783 in->pcm = NULL;
1784 }
1785 if (pcm_open_retry_count-- == 0) {
1786 ret = -EIO;
1787 goto error_open;
1788 }
1789 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1790 continue;
1791 }
1792 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001794
1795 ALOGV("%s: pcm_prepare", __func__);
1796 ret = pcm_prepare(in->pcm);
1797 if (ret < 0) {
1798 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1799 pcm_close(in->pcm);
1800 in->pcm = NULL;
1801 goto error_open;
1802 }
1803
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001804 register_in_stream(in);
1805 if (in->realtime) {
1806 ret = pcm_start(in->pcm);
1807 if (ret < 0)
1808 goto error_open;
1809 }
1810
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301811done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301812 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001813 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001814
Eric Laurentc8400632013-02-14 19:04:54 -08001815 return ret;
1816
1817error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301818 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001820error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301821 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301822 /*
1823 * sleep 50ms to allow sufficient time for kernel
1824 * drivers to recover incases like SSR.
1825 */
1826 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001828
1829 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830}
1831
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001832void lock_input_stream(struct stream_in *in)
1833{
1834 pthread_mutex_lock(&in->pre_lock);
1835 pthread_mutex_lock(&in->lock);
1836 pthread_mutex_unlock(&in->pre_lock);
1837}
1838
1839void lock_output_stream(struct stream_out *out)
1840{
1841 pthread_mutex_lock(&out->pre_lock);
1842 pthread_mutex_lock(&out->lock);
1843 pthread_mutex_unlock(&out->pre_lock);
1844}
1845
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001846/* must be called with out->lock locked */
1847static int send_offload_cmd_l(struct stream_out* out, int command)
1848{
1849 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1850
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001851 if (!cmd) {
1852 ALOGE("failed to allocate mem for command 0x%x", command);
1853 return -ENOMEM;
1854 }
1855
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 ALOGVV("%s %d", __func__, command);
1857
1858 cmd->cmd = command;
1859 list_add_tail(&out->offload_cmd_list, &cmd->node);
1860 pthread_cond_signal(&out->offload_cond);
1861 return 0;
1862}
1863
1864/* must be called iwth out->lock locked */
1865static void stop_compressed_output_l(struct stream_out *out)
1866{
1867 out->offload_state = OFFLOAD_STATE_IDLE;
1868 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001869 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 if (out->compr != NULL) {
1871 compress_stop(out->compr);
1872 while (out->offload_thread_blocked) {
1873 pthread_cond_wait(&out->cond, &out->lock);
1874 }
1875 }
1876}
1877
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001878bool is_offload_usecase(audio_usecase_t uc_id)
1879{
1880 unsigned int i;
1881 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1882 if (uc_id == offload_usecases[i])
1883 return true;
1884 }
1885 return false;
1886}
1887
vivek mehta446c3962015-09-14 10:57:35 -07001888static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001889{
vivek mehta446c3962015-09-14 10:57:35 -07001890 audio_usecase_t ret_uc = USECASE_INVALID;
1891 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001892 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001893 if (!adev->multi_offload_enable) {
1894 if (is_direct_pcm)
1895 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1896 else
1897 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001898
vivek mehta446c3962015-09-14 10:57:35 -07001899 pthread_mutex_lock(&adev->lock);
1900 if (get_usecase_from_list(adev, ret_uc) != NULL)
1901 ret_uc = USECASE_INVALID;
1902 pthread_mutex_unlock(&adev->lock);
1903
1904 return ret_uc;
1905 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001906
1907 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001908 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1909 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1910 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1911 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001912 break;
1913 }
1914 }
vivek mehta446c3962015-09-14 10:57:35 -07001915
1916 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1917 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001918}
1919
1920static void free_offload_usecase(struct audio_device *adev,
1921 audio_usecase_t uc_id)
1922{
vivek mehta446c3962015-09-14 10:57:35 -07001923 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001924 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001925
1926 if (!adev->multi_offload_enable)
1927 return;
1928
1929 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1930 if (offload_usecases[offload_uc_index] == uc_id) {
1931 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001932 break;
1933 }
1934 }
1935 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1936}
1937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001938static void *offload_thread_loop(void *context)
1939{
1940 struct stream_out *out = (struct stream_out *) context;
1941 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001942 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001944 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1945 set_sched_policy(0, SP_FOREGROUND);
1946 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1947
1948 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001949 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001950 for (;;) {
1951 struct offload_cmd *cmd = NULL;
1952 stream_callback_event_t event;
1953 bool send_callback = false;
1954
1955 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1956 __func__, list_empty(&out->offload_cmd_list),
1957 out->offload_state);
1958 if (list_empty(&out->offload_cmd_list)) {
1959 ALOGV("%s SLEEPING", __func__);
1960 pthread_cond_wait(&out->offload_cond, &out->lock);
1961 ALOGV("%s RUNNING", __func__);
1962 continue;
1963 }
1964
1965 item = list_head(&out->offload_cmd_list);
1966 cmd = node_to_item(item, struct offload_cmd, node);
1967 list_remove(item);
1968
1969 ALOGVV("%s STATE %d CMD %d out->compr %p",
1970 __func__, out->offload_state, cmd->cmd, out->compr);
1971
1972 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1973 free(cmd);
1974 break;
1975 }
1976
1977 if (out->compr == NULL) {
1978 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001979 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980 pthread_cond_signal(&out->cond);
1981 continue;
1982 }
1983 out->offload_thread_blocked = true;
1984 pthread_mutex_unlock(&out->lock);
1985 send_callback = false;
1986 switch(cmd->cmd) {
1987 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001988 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001989 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001990 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 send_callback = true;
1992 event = STREAM_CBK_EVENT_WRITE_READY;
1993 break;
1994 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001995 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301996 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001997 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301998 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001999 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302000 if (ret < 0)
2001 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302002 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302003 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002004 compress_drain(out->compr);
2005 else
2006 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302007 if (ret != -ENETRESET) {
2008 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302009 pthread_mutex_lock(&out->lock);
2010 out->send_new_metadata = 1;
2011 out->send_next_track_params = true;
2012 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302013 event = STREAM_CBK_EVENT_DRAIN_READY;
2014 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2015 } else
2016 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002017 break;
2018 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002019 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002021 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 send_callback = true;
2023 event = STREAM_CBK_EVENT_DRAIN_READY;
2024 break;
2025 default:
2026 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2027 break;
2028 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002029 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 out->offload_thread_blocked = false;
2031 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002032 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002033 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002034 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002035 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002036 free(cmd);
2037 }
2038
2039 pthread_cond_signal(&out->cond);
2040 while (!list_empty(&out->offload_cmd_list)) {
2041 item = list_head(&out->offload_cmd_list);
2042 list_remove(item);
2043 free(node_to_item(item, struct offload_cmd, node));
2044 }
2045 pthread_mutex_unlock(&out->lock);
2046
2047 return NULL;
2048}
2049
2050static int create_offload_callback_thread(struct stream_out *out)
2051{
2052 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2053 list_init(&out->offload_cmd_list);
2054 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2055 offload_thread_loop, out);
2056 return 0;
2057}
2058
2059static int destroy_offload_callback_thread(struct stream_out *out)
2060{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002061 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 stop_compressed_output_l(out);
2063 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2064
2065 pthread_mutex_unlock(&out->lock);
2066 pthread_join(out->offload_thread, (void **) NULL);
2067 pthread_cond_destroy(&out->offload_cond);
2068
2069 return 0;
2070}
2071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072static int stop_output_stream(struct stream_out *out)
2073{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302074 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 struct audio_usecase *uc_info;
2076 struct audio_device *adev = out->dev;
2077
Eric Laurent994a6932013-07-17 11:51:42 -07002078 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002079 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 uc_info = get_usecase_from_list(adev, out->usecase);
2081 if (uc_info == NULL) {
2082 ALOGE("%s: Could not find the usecase (%d) in the list",
2083 __func__, out->usecase);
2084 return -EINVAL;
2085 }
2086
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002087 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302088 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002089 if (adev->visualizer_stop_output != NULL)
2090 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002091
2092 audio_extn_dts_remove_state_notifier_node(out->usecase);
2093
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002094 if (adev->offload_effects_stop_output != NULL)
2095 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2096 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002097
Eric Laurent150dbfe2013-02-27 14:31:02 -08002098 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002099 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002100
2101 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002102 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002104 list_remove(&uc_info->list);
2105 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002107 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302108 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002109 ALOGV("Disable passthrough , reset mixer to pcm");
2110 /* NO_PASSTHROUGH */
2111 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002112 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002113 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2114 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002115
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302116 /* Must be called after removing the usecase from list */
2117 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302118 audio_extn_keep_alive_start();
2119
Eric Laurent994a6932013-07-17 11:51:42 -07002120 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 return ret;
2122}
2123
2124int start_output_stream(struct stream_out *out)
2125{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 struct audio_usecase *uc_info;
2128 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302129 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002131 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2132 ret = -EINVAL;
2133 goto error_config;
2134 }
2135
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302136 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2137 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2138 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302139
Naresh Tanniru80659832014-06-04 18:17:56 +05302140 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302141 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302142 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302143 goto error_config;
2144 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302145
Eric Laurentb23d5282013-05-14 15:27:20 -07002146 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 if (out->pcm_device_id < 0) {
2148 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2149 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002150 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002151 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 }
2153
2154 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002155
2156 if (!uc_info) {
2157 ret = -ENOMEM;
2158 goto error_config;
2159 }
2160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 uc_info->id = out->usecase;
2162 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002163 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002164 uc_info->devices = out->devices;
2165 uc_info->in_snd_device = SND_DEVICE_NONE;
2166 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002167 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302169 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2170 adev->perf_lock_opts,
2171 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302172
2173 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2174 audio_extn_keep_alive_stop();
2175 if (audio_extn_passthru_is_enabled() &&
2176 audio_extn_passthru_is_passthrough_stream(out)) {
2177 audio_extn_passthru_on_start(out);
2178 audio_extn_passthru_update_stream_configuration(adev, out);
2179 }
2180 }
2181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002182 select_devices(adev, out->usecase);
2183
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2185 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002186 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002187 unsigned int flags = PCM_OUT;
2188 unsigned int pcm_open_retry_count = 0;
2189 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2190 flags |= PCM_MMAP | PCM_NOIRQ;
2191 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002192 } else if (out->realtime) {
2193 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002194 } else
2195 flags |= PCM_MONOTONIC;
2196
2197 while (1) {
2198 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2199 flags, &out->config);
2200 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2201 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2202 if (out->pcm != NULL) {
2203 pcm_close(out->pcm);
2204 out->pcm = NULL;
2205 }
2206 if (pcm_open_retry_count-- == 0) {
2207 ret = -EIO;
2208 goto error_open;
2209 }
2210 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2211 continue;
2212 }
2213 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002215
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002216 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2217 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002218
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002219 ALOGV("%s: pcm_prepare", __func__);
2220 if (pcm_is_ready(out->pcm)) {
2221 ret = pcm_prepare(out->pcm);
2222 if (ret < 0) {
2223 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2224 pcm_close(out->pcm);
2225 out->pcm = NULL;
2226 goto error_open;
2227 }
2228 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002229 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002230 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2231 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002233 out->compr = compress_open(adev->snd_card,
2234 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 COMPRESS_IN, &out->compr_config);
2236 if (out->compr && !is_compress_ready(out->compr)) {
2237 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2238 compress_close(out->compr);
2239 out->compr = NULL;
2240 ret = -EIO;
2241 goto error_open;
2242 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302243 /* compress_open sends params of the track, so reset the flag here */
2244 out->is_compr_metadata_avail = false;
2245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 if (out->offload_callback)
2247 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002248
Fred Oh3f43e742015-03-04 18:42:34 -08002249 /* Since small bufs uses blocking writes, a write will be blocked
2250 for the default max poll time (20s) in the event of an SSR.
2251 Reduce the poll time to observe and deal with SSR faster.
2252 */
Ashish Jain5106d362016-05-11 19:23:33 +05302253 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002254 compress_set_max_poll_wait(out->compr, 1000);
2255 }
2256
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002257 audio_extn_dts_create_state_notifier_node(out->usecase);
2258 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2259 popcount(out->channel_mask),
2260 out->playback_started);
2261
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002262#ifdef DS1_DOLBY_DDP_ENABLED
2263 if (audio_extn_is_dolby_format(out->format))
2264 audio_extn_dolby_send_ddp_endp_params(adev);
2265#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302266 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002267 if (adev->visualizer_start_output != NULL)
2268 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2269 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302270 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002271 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002274
2275 if (ret == 0) {
2276 register_out_stream(out);
2277 if (out->realtime) {
2278 ret = pcm_start(out->pcm);
2279 if (ret < 0)
2280 goto error_open;
2281 }
2282 }
2283
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302284 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002285 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002286
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002287 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302289 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002291error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302292 /*
2293 * sleep 50ms to allow sufficient time for kernel
2294 * drivers to recover incases like SSR.
2295 */
2296 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002297 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298}
2299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300static int check_input_parameters(uint32_t sample_rate,
2301 audio_format_t format,
2302 int channel_count)
2303{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002304 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302306 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2307 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2308 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002309 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302310 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002311
2312 switch (channel_count) {
2313 case 1:
2314 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302315 case 3:
2316 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002317 case 6:
2318 break;
2319 default:
2320 ret = -EINVAL;
2321 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322
2323 switch (sample_rate) {
2324 case 8000:
2325 case 11025:
2326 case 12000:
2327 case 16000:
2328 case 22050:
2329 case 24000:
2330 case 32000:
2331 case 44100:
2332 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302333 case 96000:
2334 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 break;
2336 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002337 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 }
2339
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002340 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341}
2342
2343static size_t get_input_buffer_size(uint32_t sample_rate,
2344 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002345 int channel_count,
2346 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347{
2348 size_t size = 0;
2349
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002350 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2351 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002353 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002354 if (is_low_latency)
2355 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302356
2357 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002359 /* make sure the size is multiple of 32 bytes
2360 * At 48 kHz mono 16-bit PCM:
2361 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2362 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2363 */
2364 size += 0x1f;
2365 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002366
2367 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368}
2369
Ashish Jain058165c2016-09-28 23:18:48 +05302370static size_t get_output_period_size(uint32_t sample_rate,
2371 audio_format_t format,
2372 int channel_count,
2373 int duration /*in millisecs*/)
2374{
2375 size_t size = 0;
2376 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2377
2378 if ((duration == 0) || (sample_rate == 0) ||
2379 (bytes_per_sample == 0) || (channel_count == 0)) {
2380 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2381 bytes_per_sample, channel_count);
2382 return -EINVAL;
2383 }
2384
2385 size = (sample_rate *
2386 duration *
2387 bytes_per_sample *
2388 channel_count) / 1000;
2389 /*
2390 * To have same PCM samples for all channels, the buffer size requires to
2391 * be multiple of (number of channels * bytes per sample)
2392 * For writes to succeed, the buffer must be written at address which is multiple of 32
2393 */
2394 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2395
2396 return (size/(channel_count * bytes_per_sample));
2397}
2398
Ashish Jain5106d362016-05-11 19:23:33 +05302399static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2400{
2401 uint64_t actual_frames_rendered = 0;
2402 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2403
2404 /* This adjustment accounts for buffering after app processor.
2405 * It is based on estimated DSP latency per use case, rather than exact.
2406 */
2407 int64_t platform_latency = platform_render_latency(out->usecase) *
2408 out->sample_rate / 1000000LL;
2409
2410 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2411 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2412 * hence only estimate.
2413 */
2414 int64_t signed_frames = out->written - kernel_buffer_size;
2415
2416 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2417
2418 if (signed_frames > 0)
2419 actual_frames_rendered = signed_frames;
2420
2421 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2422 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2423 (long long int)out->written, (int)kernel_buffer_size,
2424 audio_bytes_per_sample(out->compr_config.codec->format),
2425 popcount(out->channel_mask));
2426
2427 return actual_frames_rendered;
2428}
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2431{
2432 struct stream_out *out = (struct stream_out *)stream;
2433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435}
2436
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002437static int out_set_sample_rate(struct audio_stream *stream __unused,
2438 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439{
2440 return -ENOSYS;
2441}
2442
2443static size_t out_get_buffer_size(const struct audio_stream *stream)
2444{
2445 struct stream_out *out = (struct stream_out *)stream;
2446
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002447 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002449 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2450 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302451 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302452 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002454 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002455 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456}
2457
2458static uint32_t out_get_channels(const struct audio_stream *stream)
2459{
2460 struct stream_out *out = (struct stream_out *)stream;
2461
2462 return out->channel_mask;
2463}
2464
2465static audio_format_t out_get_format(const struct audio_stream *stream)
2466{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002467 struct stream_out *out = (struct stream_out *)stream;
2468
2469 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470}
2471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002472static int out_set_format(struct audio_stream *stream __unused,
2473 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474{
2475 return -ENOSYS;
2476}
2477
2478static int out_standby(struct audio_stream *stream)
2479{
2480 struct stream_out *out = (struct stream_out *)stream;
2481 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302483 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2484 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002486 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002488 if (adev->adm_deregister_stream)
2489 adev->adm_deregister_stream(adev->adm_data, out->handle);
2490
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002491 if (is_offload_usecase(out->usecase))
2492 stop_compressed_output_l(out);
2493
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002494 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002496 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2497 voice_extn_compress_voip_close_output_stream(stream);
2498 pthread_mutex_unlock(&adev->lock);
2499 pthread_mutex_unlock(&out->lock);
2500 ALOGD("VOIP output entered standby");
2501 return 0;
2502 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503 if (out->pcm) {
2504 pcm_close(out->pcm);
2505 out->pcm = NULL;
2506 }
2507 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002508 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302509 out->send_next_track_params = false;
2510 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002511 out->gapless_mdata.encoder_delay = 0;
2512 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002513 if (out->compr != NULL) {
2514 compress_close(out->compr);
2515 out->compr = NULL;
2516 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 }
2521 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302522 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 return 0;
2524}
2525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002526static int out_dump(const struct audio_stream *stream __unused,
2527 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528{
2529 return 0;
2530}
2531
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002532static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2533{
2534 int ret = 0;
2535 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002536
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002537 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002538 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002539 return -EINVAL;
2540 }
2541
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302542 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002543
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002544 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2545 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302546 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002547 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002548 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2549 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302550 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002551 }
2552
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002553 ALOGV("%s new encoder delay %u and padding %u", __func__,
2554 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2555
2556 return 0;
2557}
2558
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002559static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2560{
2561 return out == adev->primary_output || out == adev->voice_tx_output;
2562}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2565{
2566 struct stream_out *out = (struct stream_out *)stream;
2567 struct audio_device *adev = out->dev;
2568 struct str_parms *parms;
2569 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002570 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571
sangwoobc677242013-08-08 16:53:43 +09002572 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002573 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302575 if (!parms)
2576 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002577 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2578 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002580 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002581 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002583 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002584 * When HDMI cable is unplugged the music playback is paused and
2585 * the policy manager sends routing=0. But the audioflinger continues
2586 * to write data until standby time (3sec). As the HDMI core is
2587 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002588 * Avoid this by routing audio to speaker until standby.
2589 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002590 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2591 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302592 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002593 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2594 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002595 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302596 /*
2597 * When A2DP is disconnected the
2598 * music playback is paused and the policy manager sends routing=0
2599 * But the audioflingercontinues to write data until standby time
2600 * (3sec). As BT is turned off, the write gets blocked.
2601 * Avoid this by routing audio to speaker until standby.
2602 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002603 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302604 (val == AUDIO_DEVICE_NONE)) {
2605 val = AUDIO_DEVICE_OUT_SPEAKER;
2606 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302607 /* To avoid a2dp to sco overlapping force route BT usecases
2608 * to speaker based on Phone state
2609 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002610 if ((val & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302611 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2612 (adev->mode == AUDIO_MODE_IN_CALL))) {
2613 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2614 val = AUDIO_DEVICE_OUT_SPEAKER;
2615 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 /*
2617 * select_devices() call below switches all the usecases on the same
2618 * backend to the new device. Refer to check_usecases_codec_backend() in
2619 * the select_devices(). But how do we undo this?
2620 *
2621 * For example, music playback is active on headset (deep-buffer usecase)
2622 * and if we go to ringtones and select a ringtone, low-latency usecase
2623 * will be started on headset+speaker. As we can't enable headset+speaker
2624 * and headset devices at the same time, select_devices() switches the music
2625 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2626 * So when the ringtone playback is completed, how do we undo the same?
2627 *
2628 * We are relying on the out_set_parameters() call on deep-buffer output,
2629 * once the ringtone playback is ended.
2630 * NOTE: We should not check if the current devices are same as new devices.
2631 * Because select_devices() must be called to switch back the music
2632 * playback to headset.
2633 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002634 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002635 audio_devices_t new_dev = val;
2636 bool same_dev = out->devices == new_dev;
2637 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002638
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002639 if (output_drives_call(adev, out)) {
2640 if(!voice_is_in_call(adev)) {
2641 if (adev->mode == AUDIO_MODE_IN_CALL) {
2642 adev->current_call_output = out;
2643 ret = voice_start_call(adev);
2644 }
2645 } else {
2646 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002647 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002648 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002649 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002650
2651 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002652 if (!same_dev) {
2653 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302654 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2655 adev->perf_lock_opts,
2656 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002657 if (adev->adm_on_routing_change)
2658 adev->adm_on_routing_change(adev->adm_data,
2659 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002660 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002661 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302662 if (!same_dev)
2663 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002664 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002665 }
2666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002668 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002670
2671 if (out == adev->primary_output) {
2672 pthread_mutex_lock(&adev->lock);
2673 audio_extn_set_parameters(adev, parms);
2674 pthread_mutex_unlock(&adev->lock);
2675 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002676 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002677 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002678 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002679
2680 audio_extn_dts_create_state_notifier_node(out->usecase);
2681 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2682 popcount(out->channel_mask),
2683 out->playback_started);
2684
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002685 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002686 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002687
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302688 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2689 if (err >= 0) {
2690 strlcpy(out->profile, value, sizeof(out->profile));
2691 ALOGV("updating stream profile with value '%s'", out->profile);
2692 lock_output_stream(out);
2693 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2694 &adev->streams_output_cfg_list,
2695 out->devices, out->flags, out->format,
2696 out->sample_rate, out->bit_width,
2697 out->channel_mask, out->profile,
2698 &out->app_type_cfg);
2699 pthread_mutex_unlock(&out->lock);
2700 }
2701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302703error:
Eric Laurent994a6932013-07-17 11:51:42 -07002704 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 return ret;
2706}
2707
2708static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2709{
2710 struct stream_out *out = (struct stream_out *)stream;
2711 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002712 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 char value[256];
2714 struct str_parms *reply = str_parms_create();
2715 size_t i, j;
2716 int ret;
2717 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002718
2719 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002720 if (reply) {
2721 str_parms_destroy(reply);
2722 }
2723 if (query) {
2724 str_parms_destroy(query);
2725 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002726 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2727 return NULL;
2728 }
2729
Eric Laurent994a6932013-07-17 11:51:42 -07002730 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2732 if (ret >= 0) {
2733 value[0] = '\0';
2734 i = 0;
2735 while (out->supported_channel_masks[i] != 0) {
2736 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2737 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2738 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002739 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002741 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 first = false;
2743 break;
2744 }
2745 }
2746 i++;
2747 }
2748 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2749 str = str_parms_to_str(reply);
2750 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002751 voice_extn_out_get_parameters(out, query, reply);
2752 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002753 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002754 free(str);
2755 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002756 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002758
Alexy Joseph62142aa2015-11-16 15:10:34 -08002759
2760 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2761 if (ret >= 0) {
2762 value[0] = '\0';
2763 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2764 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302765 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002766 } else {
2767 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302768 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002769 }
2770 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002771 if (str)
2772 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002773 str = str_parms_to_str(reply);
2774 }
2775
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002776 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2777 if (ret >= 0) {
2778 value[0] = '\0';
2779 i = 0;
2780 first = true;
2781 while (out->supported_formats[i] != 0) {
2782 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2783 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2784 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002785 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002786 }
2787 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2788 first = false;
2789 break;
2790 }
2791 }
2792 i++;
2793 }
2794 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002795 if (str)
2796 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002797 str = str_parms_to_str(reply);
2798 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002799
2800 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2801 if (ret >= 0) {
2802 value[0] = '\0';
2803 i = 0;
2804 first = true;
2805 while (out->supported_sample_rates[i] != 0) {
2806 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2807 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2808 if (!first) {
2809 strlcat(value, "|", sizeof(value));
2810 }
2811 strlcat(value, out_hdmi_sample_rates_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_SAMPLING_RATES, value);
2819 if (str)
2820 free(str);
2821 str = str_parms_to_str(reply);
2822 }
2823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 str_parms_destroy(query);
2825 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002826 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 return str;
2828}
2829
2830static uint32_t out_get_latency(const struct audio_stream_out *stream)
2831{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002832 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002834 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835
Alexy Josephaa54c872014-12-03 02:46:47 -08002836 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002837 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002838 } else if (out->realtime) {
2839 // since the buffer won't be filled up faster than realtime,
2840 // return a smaller number
2841 if (out->config.rate)
2842 period_ms = (out->af_period_multiplier * out->config.period_size *
2843 1000) / (out->config.rate);
2844 else
2845 period_ms = 0;
2846 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002847 } else {
2848 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002850 }
2851
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302852 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002853 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854}
2855
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302856static float AmpToDb(float amplification)
2857{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302858 float db = DSD_VOLUME_MIN_DB;
2859 if (amplification > 0) {
2860 db = 20 * log10(amplification);
2861 if(db < DSD_VOLUME_MIN_DB)
2862 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302863 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302864 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302865}
2866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867static int out_set_volume(struct audio_stream_out *stream, float left,
2868 float right)
2869{
Eric Laurenta9024de2013-04-04 09:19:12 -07002870 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 int volume[2];
2872
Eric Laurenta9024de2013-04-04 09:19:12 -07002873 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2874 /* only take left channel into account: the API is for stereo anyway */
2875 out->muted = (left == 0.0f);
2876 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002877 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302878 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002879 /*
2880 * Set mute or umute on HDMI passthrough stream.
2881 * Only take left channel into account.
2882 * Mute is 0 and unmute 1
2883 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302884 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302885 } else if (out->format == AUDIO_FORMAT_DSD){
2886 char mixer_ctl_name[128] = "DSD Volume";
2887 struct audio_device *adev = out->dev;
2888 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2889
2890 if (!ctl) {
2891 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2892 __func__, mixer_ctl_name);
2893 return -EINVAL;
2894 }
2895 volume[0] = (int)(AmpToDb(left));
2896 volume[1] = (int)(AmpToDb(right));
2897 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2898 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002899 } else {
2900 char mixer_ctl_name[128];
2901 struct audio_device *adev = out->dev;
2902 struct mixer_ctl *ctl;
2903 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002904 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002906 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2907 "Compress Playback %d Volume", pcm_device_id);
2908 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2909 if (!ctl) {
2910 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2911 __func__, mixer_ctl_name);
2912 return -EINVAL;
2913 }
2914 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2915 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2916 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2917 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002919 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 return -ENOSYS;
2922}
2923
2924static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2925 size_t bytes)
2926{
2927 struct stream_out *out = (struct stream_out *)stream;
2928 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302929 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002930 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002932 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302933
Naresh Tanniru80659832014-06-04 18:17:56 +05302934 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002935
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302936 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302937 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302938 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2939 pthread_mutex_unlock(&out->lock);
2940 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302941 } else {
2942 /* increase written size during SSR to avoid mismatch
2943 * with the written frames count in AF
2944 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002945 // bytes per frame
2946 size_t bpf = audio_bytes_per_sample(out->format) *
2947 audio_channel_count_from_out_mask(out->channel_mask);
2948 if (bpf != 0)
2949 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302950 ALOGD(" %s: sound card is not active/SSR state", __func__);
2951 ret= -EIO;
2952 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302953 }
2954 }
2955
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302956 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302957 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2958 if (audio_bytes_per_sample(out->format) != 0)
2959 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2960 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302961 goto exit;
2962 }
2963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002965 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002966 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002967 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2968 ret = voice_extn_compress_voip_start_output_stream(out);
2969 else
2970 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002971 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002972 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002974 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 goto exit;
2976 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002977
2978 if (last_known_cal_step != -1) {
2979 ALOGD("%s: retry previous failed cal level set", __func__);
2980 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983
Ashish Jain81eb2a82015-05-13 10:52:34 +05302984 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002985 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302986 adev->is_channel_status_set = true;
2987 }
2988
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002989 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002990 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002991 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002992 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002993 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2994 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302995 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2996 ALOGD("copl(%p):send next track params in gapless", out);
2997 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2998 out->send_next_track_params = false;
2999 out->is_compr_metadata_avail = false;
3000 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003001 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303002 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303003 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003004
Ashish Jain83a6cc22016-06-28 14:34:17 +05303005 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303006 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303007 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303008 pthread_mutex_unlock(&out->lock);
3009 return -EINVAL;
3010 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303011 audio_format_t dst_format = out->hal_op_format;
3012 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303013
3014 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3015 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3016
Ashish Jain83a6cc22016-06-28 14:34:17 +05303017 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303018 dst_format,
3019 buffer,
3020 src_format,
3021 frames);
3022
Ashish Jain83a6cc22016-06-28 14:34:17 +05303023 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303024 bytes_to_write);
3025
3026 /*Convert written bytes in audio flinger format*/
3027 if (ret > 0)
3028 ret = ((ret * format_to_bitwidth_table[out->format]) /
3029 format_to_bitwidth_table[dst_format]);
3030 }
3031 } else
3032 ret = compress_write(out->compr, buffer, bytes);
3033
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303034 if (ret < 0)
3035 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303036 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303037 /*msg to cb thread only if non blocking write is enabled*/
3038 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303039 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303041 } else if (-ENETRESET == ret) {
3042 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3043 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3044 pthread_mutex_unlock(&out->lock);
3045 out_standby(&out->stream.common);
3046 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 }
Ashish Jain5106d362016-05-11 19:23:33 +05303048 if ( ret == (ssize_t)bytes && !out->non_blocking)
3049 out->written += bytes;
3050
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303051 /* Call compr start only when non-zero bytes of data is there to be rendered */
3052 if (!out->playback_started && ret > 0) {
3053 int status = compress_start(out->compr);
3054 if (status < 0) {
3055 ret = status;
3056 ALOGE("%s: compr start failed with err %d", __func__, errno);
3057 goto exit;
3058 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003059 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 out->playback_started = 1;
3061 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003062
3063 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3064 popcount(out->channel_mask),
3065 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 }
3067 pthread_mutex_unlock(&out->lock);
3068 return ret;
3069 } else {
3070 if (out->pcm) {
3071 if (out->muted)
3072 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003073
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303074 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003075
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003076 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003077
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003078 if (out->config.rate)
3079 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3080 out->config.rate;
3081
3082 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3083
3084 request_out_focus(out, ns);
3085
3086 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003087 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003088 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303089 out->convert_buffer != NULL) {
3090
3091 memcpy_by_audio_format(out->convert_buffer,
3092 out->hal_op_format,
3093 buffer,
3094 out->hal_ip_format,
3095 out->config.period_size * out->config.channels);
3096
3097 ret = pcm_write(out->pcm, out->convert_buffer,
3098 (out->config.period_size *
3099 out->config.channels *
3100 format_to_bitwidth_table[out->hal_op_format]));
3101 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003102 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303103 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003104
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003105 release_out_focus(out);
3106
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303107 if (ret < 0)
3108 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303109 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3110 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3111 else
3112 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 }
3115
3116exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303117 /* ToDo: There may be a corner case when SSR happens back to back during
3118 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303119 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303120 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303121 }
3122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 pthread_mutex_unlock(&out->lock);
3124
3125 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003126 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003127 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303128 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303129 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303130 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303131 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303132 out->standby = true;
3133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303135 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3136 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3137 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 }
3139 return bytes;
3140}
3141
3142static int out_get_render_position(const struct audio_stream_out *stream,
3143 uint32_t *dsp_frames)
3144{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303146 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003147
3148 if (dsp_frames == NULL)
3149 return -EINVAL;
3150
3151 *dsp_frames = 0;
3152 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003153 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303154
3155 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3156 * this operation and adev_close_output_stream(where out gets reset).
3157 */
3158 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3159 *dsp_frames = get_actual_pcm_frames_rendered(out);
3160 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3161 return 0;
3162 }
3163
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003164 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303165 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303166 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303168 if (ret < 0)
3169 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303171 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 }
3173 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303174 if (-ENETRESET == ret) {
3175 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3176 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3177 return -EINVAL;
3178 } else if(ret < 0) {
3179 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3180 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303181 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3182 /*
3183 * Handle corner case where compress session is closed during SSR
3184 * and timestamp is queried
3185 */
3186 ALOGE(" ERROR: sound card not active, return error");
3187 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303188 } else {
3189 return 0;
3190 }
Zhou Song32a556e2015-05-05 10:46:56 +08003191 } else if (audio_is_linear_pcm(out->format)) {
3192 *dsp_frames = out->written;
3193 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003194 } else
3195 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196}
3197
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003198static int out_add_audio_effect(const struct audio_stream *stream __unused,
3199 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200{
3201 return 0;
3202}
3203
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003204static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3205 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206{
3207 return 0;
3208}
3209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003210static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3211 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212{
3213 return -EINVAL;
3214}
3215
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003216static int out_get_presentation_position(const struct audio_stream_out *stream,
3217 uint64_t *frames, struct timespec *timestamp)
3218{
3219 struct stream_out *out = (struct stream_out *)stream;
3220 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003221 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003222
Ashish Jain5106d362016-05-11 19:23:33 +05303223 /* below piece of code is not guarded against any lock because audioFliner serializes
3224 * this operation and adev_close_output_stream( where out gets reset).
3225 */
3226 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3227 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3228 *frames = get_actual_pcm_frames_rendered(out);
3229 /* this is the best we can do */
3230 clock_gettime(CLOCK_MONOTONIC, timestamp);
3231 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3232 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3233 return 0;
3234 }
3235
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003236 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003237
Ashish Jain5106d362016-05-11 19:23:33 +05303238 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3239 ret = compress_get_tstamp(out->compr, &dsp_frames,
3240 &out->sample_rate);
3241 ALOGVV("%s rendered frames %ld sample_rate %d",
3242 __func__, dsp_frames, out->sample_rate);
3243 *frames = dsp_frames;
3244 if (ret < 0)
3245 ret = -errno;
3246 if (-ENETRESET == ret) {
3247 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3248 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3249 ret = -EINVAL;
3250 } else
3251 ret = 0;
3252 /* this is the best we can do */
3253 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003254 } else {
3255 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003256 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003257 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3258 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003259 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003260 // This adjustment accounts for buffering after app processor.
3261 // It is based on estimated DSP latency per use case, rather than exact.
3262 signed_frames -=
3263 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3264
Eric Laurent949a0892013-09-20 09:20:13 -07003265 // It would be unusual for this value to be negative, but check just in case ...
3266 if (signed_frames >= 0) {
3267 *frames = signed_frames;
3268 ret = 0;
3269 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003270 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303271 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3272 *frames = out->written;
3273 clock_gettime(CLOCK_MONOTONIC, timestamp);
3274 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003275 }
3276 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003277 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003278 return ret;
3279}
3280
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003281static int out_set_callback(struct audio_stream_out *stream,
3282 stream_callback_t callback, void *cookie)
3283{
3284 struct stream_out *out = (struct stream_out *)stream;
3285
3286 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003287 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 out->offload_callback = callback;
3289 out->offload_cookie = cookie;
3290 pthread_mutex_unlock(&out->lock);
3291 return 0;
3292}
3293
3294static int out_pause(struct audio_stream_out* stream)
3295{
3296 struct stream_out *out = (struct stream_out *)stream;
3297 int status = -ENOSYS;
3298 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003299 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003300 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003301 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003302 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303303 struct audio_device *adev = out->dev;
3304 int snd_scard_state = get_snd_card_state(adev);
3305
3306 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3307 status = compress_pause(out->compr);
3308
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003310
Mingming Yin21854652016-04-13 11:54:02 -07003311 if (audio_extn_passthru_is_active()) {
3312 ALOGV("offload use case, pause passthru");
3313 audio_extn_passthru_on_pause(out);
3314 }
3315
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303316 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003317 audio_extn_dts_notify_playback_state(out->usecase, 0,
3318 out->sample_rate, popcount(out->channel_mask),
3319 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003320 }
3321 pthread_mutex_unlock(&out->lock);
3322 }
3323 return status;
3324}
3325
3326static int out_resume(struct audio_stream_out* stream)
3327{
3328 struct stream_out *out = (struct stream_out *)stream;
3329 int status = -ENOSYS;
3330 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003331 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003332 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003333 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003334 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303336 struct audio_device *adev = out->dev;
3337 int snd_scard_state = get_snd_card_state(adev);
3338
Mingming Yin21854652016-04-13 11:54:02 -07003339 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3340 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3341 pthread_mutex_lock(&out->dev->lock);
3342 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003343 pthread_mutex_unlock(&out->dev->lock);
3344 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303345 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003346 }
3347 if (!status) {
3348 out->offload_state = OFFLOAD_STATE_PLAYING;
3349 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303350 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003351 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3352 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 }
3354 pthread_mutex_unlock(&out->lock);
3355 }
3356 return status;
3357}
3358
3359static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3360{
3361 struct stream_out *out = (struct stream_out *)stream;
3362 int status = -ENOSYS;
3363 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003364 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003365 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3367 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3368 else
3369 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3370 pthread_mutex_unlock(&out->lock);
3371 }
3372 return status;
3373}
3374
3375static int out_flush(struct audio_stream_out* stream)
3376{
3377 struct stream_out *out = (struct stream_out *)stream;
3378 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003379 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003380 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003381 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003382 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3383 stop_compressed_output_l(out);
3384 out->written = 0;
3385 } else {
3386 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3387 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003389 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003390 return 0;
3391 }
3392 return -ENOSYS;
3393}
3394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395/** audio_stream_in implementation **/
3396static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3397{
3398 struct stream_in *in = (struct stream_in *)stream;
3399
3400 return in->config.rate;
3401}
3402
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003403static int in_set_sample_rate(struct audio_stream *stream __unused,
3404 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405{
3406 return -ENOSYS;
3407}
3408
3409static size_t in_get_buffer_size(const struct audio_stream *stream)
3410{
3411 struct stream_in *in = (struct stream_in *)stream;
3412
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003413 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3414 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003415 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3416 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303417 else if(audio_extn_cin_attached_usecase(in->usecase))
3418 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003419
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003420 return in->config.period_size * in->af_period_multiplier *
3421 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422}
3423
3424static uint32_t in_get_channels(const struct audio_stream *stream)
3425{
3426 struct stream_in *in = (struct stream_in *)stream;
3427
3428 return in->channel_mask;
3429}
3430
3431static audio_format_t in_get_format(const struct audio_stream *stream)
3432{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003433 struct stream_in *in = (struct stream_in *)stream;
3434
3435 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436}
3437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003438static int in_set_format(struct audio_stream *stream __unused,
3439 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
3441 return -ENOSYS;
3442}
3443
3444static int in_standby(struct audio_stream *stream)
3445{
3446 struct stream_in *in = (struct stream_in *)stream;
3447 struct audio_device *adev = in->dev;
3448 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303449 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3450 stream, in->usecase, use_case_table[in->usecase]);
3451
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003452 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003453 if (!in->standby && in->is_st_session) {
3454 ALOGD("%s: sound trigger pcm stop lab", __func__);
3455 audio_extn_sound_trigger_stop_lab(in);
3456 in->standby = 1;
3457 }
3458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003460 if (adev->adm_deregister_stream)
3461 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3462
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003463 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003465 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3466 voice_extn_compress_voip_close_input_stream(stream);
3467 ALOGD("VOIP input entered standby");
3468 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303469 if (audio_extn_cin_attached_usecase(in->usecase))
3470 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003471 if (in->pcm) {
3472 pcm_close(in->pcm);
3473 in->pcm = NULL;
3474 }
3475 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003476 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003477 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478 }
3479 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003480 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 return status;
3482}
3483
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003484static int in_dump(const struct audio_stream *stream __unused,
3485 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486{
3487 return 0;
3488}
3489
3490static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3491{
3492 struct stream_in *in = (struct stream_in *)stream;
3493 struct audio_device *adev = in->dev;
3494 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003496 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303498 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 parms = str_parms_create_str(kvpairs);
3500
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303501 if (!parms)
3502 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003503 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003504 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003505
3506 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3507 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 val = atoi(value);
3509 /* no audio source uses val == 0 */
3510 if ((in->source != val) && (val != 0)) {
3511 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003512 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3513 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3514 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003515 (in->config.rate == 8000 || in->config.rate == 16000 ||
3516 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003517 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003518 err = voice_extn_compress_voip_open_input_stream(in);
3519 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003520 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003521 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003522 }
3523 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 }
3525 }
3526
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003527 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3528 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003530 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 in->device = val;
3532 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003533 if (!in->standby && !in->is_st_session) {
3534 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003535 if (adev->adm_on_routing_change)
3536 adev->adm_on_routing_change(adev->adm_data,
3537 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003538 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 }
3541 }
3542
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303543 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3544 if (err >= 0) {
3545 strlcpy(in->profile, value, sizeof(in->profile));
3546 ALOGV("updating stream profile with value '%s'", in->profile);
3547 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3548 &adev->streams_input_cfg_list,
3549 in->device, in->flags, in->format,
3550 in->sample_rate, in->bit_width,
3551 in->profile, &in->app_type_cfg);
3552 }
3553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003555 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556
3557 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303558error:
Eric Laurent994a6932013-07-17 11:51:42 -07003559 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 return ret;
3561}
3562
3563static char* in_get_parameters(const struct audio_stream *stream,
3564 const char *keys)
3565{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003566 struct stream_in *in = (struct stream_in *)stream;
3567 struct str_parms *query = str_parms_create_str(keys);
3568 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003569 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003570
3571 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003572 if (reply) {
3573 str_parms_destroy(reply);
3574 }
3575 if (query) {
3576 str_parms_destroy(query);
3577 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003578 ALOGE("in_get_parameters: failed to create query or reply");
3579 return NULL;
3580 }
3581
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003582 ALOGV("%s: enter: keys - %s", __func__, keys);
3583
3584 voice_extn_in_get_parameters(in, query, reply);
3585
3586 str = str_parms_to_str(reply);
3587 str_parms_destroy(query);
3588 str_parms_destroy(reply);
3589
3590 ALOGV("%s: exit: returns - %s", __func__, str);
3591 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592}
3593
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003594static int in_set_gain(struct audio_stream_in *stream __unused,
3595 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596{
3597 return 0;
3598}
3599
3600static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3601 size_t bytes)
3602{
3603 struct stream_in *in = (struct stream_in *)stream;
3604 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303605 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303606 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303607 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003609 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303610
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003611 if (in->is_st_session) {
3612 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3613 /* Read from sound trigger HAL */
3614 audio_extn_sound_trigger_read(in, buffer, bytes);
3615 pthread_mutex_unlock(&in->lock);
3616 return bytes;
3617 }
3618
Ashish Jainbbce4322016-02-16 13:25:27 +05303619 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003620 ALOGD(" %s: sound card is not active/SSR state", __func__);
3621 ret= -EIO;;
3622 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303623 }
3624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003626 pthread_mutex_lock(&adev->lock);
3627 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3628 ret = voice_extn_compress_voip_start_input_stream(in);
3629 else
3630 ret = start_input_stream(in);
3631 pthread_mutex_unlock(&adev->lock);
3632 if (ret != 0) {
3633 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 }
3635 in->standby = 0;
3636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003638 // what's the duration requested by the client?
3639 long ns = 0;
3640
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303641 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003642 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3643 in->config.rate;
3644
3645 request_in_focus(in, ns);
3646 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003647
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303648 if (audio_extn_cin_attached_usecase(in->usecase)) {
3649 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3650 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303651 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003652 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303653 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003654 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003655 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003656 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303657 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003658 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303659 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3660 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3661 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3662 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303663 ret = -EINVAL;
3664 goto exit;
3665 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303666 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303667 ret = -errno;
3668 }
3669 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303670 /* bytes read is always set to bytes for non compress usecases */
3671 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 }
3673
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003674 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 /*
3677 * Instead of writing zeroes here, we could trust the hardware
3678 * to always provide zeroes when muted.
3679 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303680 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3681 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 memset(buffer, 0, bytes);
3683
3684exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303685 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303686 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003687 if (-ENETRESET == ret)
3688 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 pthread_mutex_unlock(&in->lock);
3691
3692 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303693 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303694 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303695 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303696 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303697 in->standby = true;
3698 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303699 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003701 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303702 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303703 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303705 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706}
3707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003708static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709{
3710 return 0;
3711}
3712
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003713static int add_remove_audio_effect(const struct audio_stream *stream,
3714 effect_handle_t effect,
3715 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003717 struct stream_in *in = (struct stream_in *)stream;
3718 int status = 0;
3719 effect_descriptor_t desc;
3720
3721 status = (*effect)->get_descriptor(effect, &desc);
3722 if (status != 0)
3723 return status;
3724
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003725 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003726 pthread_mutex_lock(&in->dev->lock);
3727 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3728 in->enable_aec != enable &&
3729 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3730 in->enable_aec = enable;
3731 if (!in->standby)
3732 select_devices(in->dev, in->usecase);
3733 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003734 if (in->enable_ns != enable &&
3735 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3736 in->enable_ns = enable;
3737 if (!in->standby)
3738 select_devices(in->dev, in->usecase);
3739 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003740 pthread_mutex_unlock(&in->dev->lock);
3741 pthread_mutex_unlock(&in->lock);
3742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 return 0;
3744}
3745
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003746static int in_add_audio_effect(const struct audio_stream *stream,
3747 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748{
Eric Laurent994a6932013-07-17 11:51:42 -07003749 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003750 return add_remove_audio_effect(stream, effect, true);
3751}
3752
3753static int in_remove_audio_effect(const struct audio_stream *stream,
3754 effect_handle_t effect)
3755{
Eric Laurent994a6932013-07-17 11:51:42 -07003756 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003757 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758}
3759
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303760int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761 audio_io_handle_t handle,
3762 audio_devices_t devices,
3763 audio_output_flags_t flags,
3764 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003765 struct audio_stream_out **stream_out,
3766 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767{
3768 struct audio_device *adev = (struct audio_device *)dev;
3769 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303770 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003771 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303774
3775 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3776 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003777 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303778 return -EINVAL;
3779 }
3780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3782
Mingming Yin3a941d42016-02-17 18:08:05 -08003783 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3784 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303785 devices, flags, &out->stream);
3786
3787
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003788 if (!out) {
3789 return -ENOMEM;
3790 }
3791
Haynes Mathew George204045b2015-02-25 20:32:03 -08003792 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003793 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003794 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 if (devices == AUDIO_DEVICE_NONE)
3797 devices = AUDIO_DEVICE_OUT_SPEAKER;
3798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 out->flags = flags;
3800 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003801 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003802 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003803 out->sample_rate = config->sample_rate;
3804 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3805 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003806 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003807 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003808 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303809 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810
Mingming Yin3a941d42016-02-17 18:08:05 -08003811 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3812 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3813 pthread_mutex_lock(&adev->lock);
3814 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3815 ret = read_hdmi_sink_caps(out);
3816 pthread_mutex_unlock(&adev->lock);
3817 if (ret != 0) {
3818 if (ret == -ENOSYS) {
3819 /* ignore and go with default */
3820 ret = 0;
3821 } else {
3822 ALOGE("error reading hdmi sink caps");
3823 goto error_open;
3824 }
3825 }
3826 }
3827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003829 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303830 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3831 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003832 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3833 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3834
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003835 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003836 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3837 /*
3838 * Do not handle stereo output in Multi-channel cases
3839 * Stereo case is handled in normal playback path
3840 */
3841 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3842 ret = AUDIO_CHANNEL_OUT_STEREO;
3843 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003844
3845 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3846 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003847 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003848 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003849 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003850
3851 if (config->sample_rate == 0)
3852 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3853 if (config->channel_mask == 0)
3854 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003855 if (config->format == 0)
3856 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003857
3858 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003859 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003860 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3862 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003864 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003866 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3867 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003868 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003869 ret = voice_extn_compress_voip_open_output_stream(out);
3870 if (ret != 0) {
3871 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3872 __func__, ret);
3873 goto error_open;
3874 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003875 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3876 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003878 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3879 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3880 ALOGE("%s: Unsupported Offload information", __func__);
3881 ret = -EINVAL;
3882 goto error_open;
3883 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003884
Mingming Yin3a941d42016-02-17 18:08:05 -08003885 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003886 if(config->offload_info.format == 0)
3887 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003888 if (config->offload_info.sample_rate == 0)
3889 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003890 }
3891
Mingming Yin90310102013-11-13 16:57:00 -08003892 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303893 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003894 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003895 ret = -EINVAL;
3896 goto error_open;
3897 }
3898
3899 out->compr_config.codec = (struct snd_codec *)
3900 calloc(1, sizeof(struct snd_codec));
3901
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003902 if (!out->compr_config.codec) {
3903 ret = -ENOMEM;
3904 goto error_open;
3905 }
3906
vivek mehta0ea887a2015-08-26 14:01:20 -07003907 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303908 out->stream.pause = out_pause;
3909 out->stream.flush = out_flush;
3910 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003911 out->usecase = get_offload_usecase(adev, true);
3912 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003913 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003914 out->stream.set_callback = out_set_callback;
3915 out->stream.pause = out_pause;
3916 out->stream.resume = out_resume;
3917 out->stream.drain = out_drain;
3918 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003919 out->usecase = get_offload_usecase(adev, false);
3920 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003921 }
vivek mehta446c3962015-09-14 10:57:35 -07003922
3923 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003924 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3925 config->format == 0 && config->sample_rate == 0 &&
3926 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003927 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003928 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3929 } else {
3930 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3931 ret = -EEXIST;
3932 goto error_open;
3933 }
vivek mehta446c3962015-09-14 10:57:35 -07003934 }
3935
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003936 if (config->offload_info.channel_mask)
3937 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003938 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003940 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003941 } else {
3942 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3943 ret = -EINVAL;
3944 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003945 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003946
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003947 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 out->sample_rate = config->offload_info.sample_rate;
3949
Mingming Yin3ee55c62014-08-04 14:23:35 -07003950 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303952 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3953 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3954 audio_extn_dolby_send_ddp_endp_params(adev);
3955 audio_extn_dolby_set_dmid(adev);
3956 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003958 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003959 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 out->compr_config.codec->bit_rate =
3961 config->offload_info.bit_rate;
3962 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303963 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303965 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003966 /*TODO: Do we need to change it for passthrough */
3967 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003968
Manish Dewangana6fc5442015-08-24 20:30:31 +05303969 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3970 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3971 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3972 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303973
3974 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3975 AUDIO_FORMAT_PCM) {
3976
3977 /*Based on platform support, configure appropriate alsa format for corresponding
3978 *hal input format.
3979 */
3980 out->compr_config.codec->format = hal_format_to_alsa(
3981 config->offload_info.format);
3982
Ashish Jain83a6cc22016-06-28 14:34:17 +05303983 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303984 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303985 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303986
3987 /*for direct PCM playback populate bit_width based on selected alsa format as
3988 *hal input format and alsa format might differ based on platform support.
3989 */
3990 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303991 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303992
3993 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3994
3995 /* Check if alsa session is configured with the same format as HAL input format,
3996 * if not then derive correct fragment size needed to accomodate the
3997 * conversion of HAL input format to alsa format.
3998 */
3999 audio_extn_utils_update_direct_pcm_fragment_size(out);
4000
4001 /*if hal input and output fragment size is different this indicates HAL input format is
4002 *not same as the alsa format
4003 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304004 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304005 /*Allocate a buffer to convert input data to the alsa configured format.
4006 *size of convert buffer is equal to the size required to hold one fragment size
4007 *worth of pcm data, this is because flinger does not write more than fragment_size
4008 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304009 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4010 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304011 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4012 ret = -ENOMEM;
4013 goto error_open;
4014 }
4015 }
4016 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4017 out->compr_config.fragment_size =
4018 audio_extn_passthru_get_buffer_size(&config->offload_info);
4019 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4020 } else {
4021 out->compr_config.fragment_size =
4022 platform_get_compress_offload_buffer_size(&config->offload_info);
4023 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4024 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004025
Amit Shekhar6f461b12014-08-01 14:52:58 -07004026 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304027 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004029 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4030 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004031
Alexy Josephaa54c872014-12-03 02:46:47 -08004032
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004033 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304034 out->send_next_track_params = false;
4035 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004036 out->offload_state = OFFLOAD_STATE_IDLE;
4037 out->playback_started = 0;
4038
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004039 audio_extn_dts_create_state_notifier_node(out->usecase);
4040
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004041 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4042 __func__, config->offload_info.version,
4043 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304044
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304045 /* Check if DSD audio format is supported in codec
4046 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304047 */
4048
4049 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304050 (!platform_check_codec_dsd_support(adev->platform) ||
4051 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304052 ret = -EINVAL;
4053 goto error_open;
4054 }
4055
Ashish Jain5106d362016-05-11 19:23:33 +05304056 /* Disable gapless if any of the following is true
4057 * passthrough playback
4058 * AV playback
4059 * Direct PCM playback
4060 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304061 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304062 (config->format == AUDIO_FORMAT_DSD) ||
4063 config->offload_info.has_video ||
4064 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304065 check_and_set_gapless_mode(adev, false);
4066 } else
4067 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004068
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304069 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004070 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4071 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304072 if (config->format == AUDIO_FORMAT_DSD) {
4073 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4074 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4075 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004076
4077 create_offload_callback_thread(out);
4078
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004079 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304080 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004081 if (ret != 0) {
4082 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4083 __func__, ret);
4084 goto error_open;
4085 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004086 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4087 if (config->sample_rate == 0)
4088 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4089 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4090 config->sample_rate != 8000) {
4091 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4092 ret = -EINVAL;
4093 goto error_open;
4094 }
4095 out->sample_rate = config->sample_rate;
4096 out->config.rate = config->sample_rate;
4097 if (config->format == AUDIO_FORMAT_DEFAULT)
4098 config->format = AUDIO_FORMAT_PCM_16_BIT;
4099 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4100 config->format = AUDIO_FORMAT_PCM_16_BIT;
4101 ret = -EINVAL;
4102 goto error_open;
4103 }
4104 out->format = config->format;
4105 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4106 out->config = pcm_config_afe_proxy_playback;
4107 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004108 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304109 unsigned int channels = 0;
4110 /*Update config params to default if not set by the caller*/
4111 if (config->sample_rate == 0)
4112 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4113 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4114 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4115 if (config->format == AUDIO_FORMAT_DEFAULT)
4116 config->format = AUDIO_FORMAT_PCM_16_BIT;
4117
4118 channels = audio_channel_count_from_out_mask(out->channel_mask);
4119
Ashish Jain83a6cc22016-06-28 14:34:17 +05304120 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4121 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004122 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4123 out->flags);
4124 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304125 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4126 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4127 out->config = pcm_config_low_latency;
4128 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4129 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4130 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304131 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4132 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4133 if (out->config.period_size <= 0) {
4134 ALOGE("Invalid configuration period size is not valid");
4135 ret = -EINVAL;
4136 goto error_open;
4137 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304138 } else {
4139 /* primary path is the default path selected if no other outputs are available/suitable */
4140 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4141 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4142 }
4143 out->hal_ip_format = format = out->format;
4144 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4145 out->hal_op_format = pcm_format_to_hal(out->config.format);
4146 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4147 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004148 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304149 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304150 if (out->hal_ip_format != out->hal_op_format) {
4151 uint32_t buffer_size = out->config.period_size *
4152 format_to_bitwidth_table[out->hal_op_format] *
4153 out->config.channels;
4154 out->convert_buffer = calloc(1, buffer_size);
4155 if (out->convert_buffer == NULL){
4156 ALOGE("Allocation failed for convert buffer for size %d",
4157 out->compr_config.fragment_size);
4158 ret = -ENOMEM;
4159 goto error_open;
4160 }
4161 ALOGD("Convert buffer allocated of size %d", buffer_size);
4162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 }
4164
Ashish Jain83a6cc22016-06-28 14:34:17 +05304165 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4166 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4167
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004168 /* TODO remove this hardcoding and check why width is zero*/
4169 if (out->bit_width == 0)
4170 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304171 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004172 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004173 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304174 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304175 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004176 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4177 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4178 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004179 if(adev->primary_output == NULL)
4180 adev->primary_output = out;
4181 else {
4182 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004183 ret = -EEXIST;
4184 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004185 }
4186 }
4187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 /* Check if this usecase is already existing */
4189 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004190 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4191 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004194 ret = -EEXIST;
4195 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 }
4197 pthread_mutex_unlock(&adev->lock);
4198
4199 out->stream.common.get_sample_rate = out_get_sample_rate;
4200 out->stream.common.set_sample_rate = out_set_sample_rate;
4201 out->stream.common.get_buffer_size = out_get_buffer_size;
4202 out->stream.common.get_channels = out_get_channels;
4203 out->stream.common.get_format = out_get_format;
4204 out->stream.common.set_format = out_set_format;
4205 out->stream.common.standby = out_standby;
4206 out->stream.common.dump = out_dump;
4207 out->stream.common.set_parameters = out_set_parameters;
4208 out->stream.common.get_parameters = out_get_parameters;
4209 out->stream.common.add_audio_effect = out_add_audio_effect;
4210 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4211 out->stream.get_latency = out_get_latency;
4212 out->stream.set_volume = out_set_volume;
4213 out->stream.write = out_write;
4214 out->stream.get_render_position = out_get_render_position;
4215 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004216 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004218 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004220 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004221 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222
4223 config->format = out->stream.common.get_format(&out->stream.common);
4224 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4225 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4226
4227 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304228 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004229 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004230
4231 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4232 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4233 popcount(out->channel_mask), out->playback_started);
4234
Eric Laurent994a6932013-07-17 11:51:42 -07004235 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004237
4238error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304239 if (out->convert_buffer)
4240 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004241 free(out);
4242 *stream_out = NULL;
4243 ALOGD("%s: exit: ret %d", __func__, ret);
4244 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245}
4246
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304247void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 struct audio_stream_out *stream)
4249{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004250 struct stream_out *out = (struct stream_out *)stream;
4251 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004252 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004253
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304254 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4255
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004256 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304257 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004258 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304259 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004260 if(ret != 0)
4261 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4262 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004263 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004264 out_standby(&stream->common);
4265
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004266 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004267 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004268 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004269 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004270 if (out->compr_config.codec != NULL)
4271 free(out->compr_config.codec);
4272 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004273
Ashish Jain83a6cc22016-06-28 14:34:17 +05304274 if (out->convert_buffer != NULL) {
4275 free(out->convert_buffer);
4276 out->convert_buffer = NULL;
4277 }
4278
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004279 if (adev->voice_tx_output == out)
4280 adev->voice_tx_output = NULL;
4281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004282 pthread_cond_destroy(&out->cond);
4283 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004285 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286}
4287
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004288static void close_compress_sessions(struct audio_device *adev)
4289{
Mingming Yin7b762e72015-03-04 13:47:32 -08004290 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304291 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004292 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004293 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304294
4295 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004296 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304297 if (is_offload_usecase(usecase->id)) {
4298 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004299 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4300 out = usecase->stream.out;
4301 pthread_mutex_unlock(&adev->lock);
4302 out_standby(&out->stream.common);
4303 pthread_mutex_lock(&adev->lock);
4304 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304305 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004306 }
4307 pthread_mutex_unlock(&adev->lock);
4308}
4309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4311{
4312 struct audio_device *adev = (struct audio_device *)dev;
4313 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004315 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004316 int ret;
4317 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004319 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304322 if (!parms)
4323 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004324 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4325 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304326 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304327 if (strstr(snd_card_status, "OFFLINE")) {
4328 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304329 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004330 //close compress sessions on OFFLINE status
4331 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304332 } else if (strstr(snd_card_status, "ONLINE")) {
4333 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304334 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004335 //send dts hpx license if enabled
4336 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304337 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304338 }
4339
4340 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004341 status = voice_set_parameters(adev, parms);
4342 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004343 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004345 status = platform_set_parameters(adev->platform, parms);
4346 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004347 goto done;
4348
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004349 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4350 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004351 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4353 adev->bluetooth_nrec = true;
4354 else
4355 adev->bluetooth_nrec = false;
4356 }
4357
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004358 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4359 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4361 adev->screen_off = false;
4362 else
4363 adev->screen_off = true;
4364 }
4365
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004366 ret = str_parms_get_int(parms, "rotation", &val);
4367 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004368 bool reverse_speakers = false;
4369 switch(val) {
4370 // FIXME: note that the code below assumes that the speakers are in the correct placement
4371 // relative to the user when the device is rotated 90deg from its default rotation. This
4372 // assumption is device-specific, not platform-specific like this code.
4373 case 270:
4374 reverse_speakers = true;
4375 break;
4376 case 0:
4377 case 90:
4378 case 180:
4379 break;
4380 default:
4381 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004382 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004383 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004384 if (status == 0) {
4385 if (adev->speaker_lr_swap != reverse_speakers) {
4386 adev->speaker_lr_swap = reverse_speakers;
4387 // only update the selected device if there is active pcm playback
4388 struct audio_usecase *usecase;
4389 struct listnode *node;
4390 list_for_each(node, &adev->usecase_list) {
4391 usecase = node_to_item(node, struct audio_usecase, list);
4392 if (usecase->type == PCM_PLAYBACK) {
4393 select_devices(adev, usecase->id);
4394 break;
4395 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004396 }
4397 }
4398 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004399 }
4400
Mingming Yin514a8bc2014-07-29 15:22:21 -07004401 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4402 if (ret >= 0) {
4403 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4404 adev->bt_wb_speech_enabled = true;
4405 else
4406 adev->bt_wb_speech_enabled = false;
4407 }
4408
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004409 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4410 if (ret >= 0) {
4411 val = atoi(value);
4412 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004413 ALOGV("cache new ext disp type and edid");
4414 ret = platform_get_ext_disp_type(adev->platform);
4415 if (ret < 0) {
4416 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004417 status = ret;
4418 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004419 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004420 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004421 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004422 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004423 /*
4424 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4425 * Per AudioPolicyManager, USB device is higher priority than WFD.
4426 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4427 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4428 * starting voice call on USB
4429 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004430 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4431 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004432 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4433 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004434 }
vivek mehta344576a2016-04-12 18:56:03 -07004435 ALOGV("detected USB connect .. disable proxy");
4436 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004437 }
4438 }
4439
4440 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4441 if (ret >= 0) {
4442 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004443 /*
4444 * The HDMI / Displayport disconnect handling has been moved to
4445 * audio extension to ensure that its parameters are not
4446 * invalidated prior to updating sysfs of the disconnect event
4447 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4448 */
4449 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004450 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004451 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4452 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304453 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4454 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004455 }
vivek mehta344576a2016-04-12 18:56:03 -07004456 ALOGV("detected USB disconnect .. enable proxy");
4457 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004458 }
4459 }
4460
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304461 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4462 if (ret >= 0) {
4463 struct audio_usecase *usecase;
4464 struct listnode *node;
4465 list_for_each(node, &adev->usecase_list) {
4466 usecase = node_to_item(node, struct audio_usecase, list);
4467 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004468 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304469 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304470 lock_output_stream(usecase->stream.out);
4471 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304472 //force device switch to re configure encoder
4473 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304474 audio_extn_a2dp_set_handoff_mode(false);
4475 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304476 break;
4477 }
4478 }
4479 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304480 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004481done:
4482 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004483 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304484error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004485 ALOGV("%s: exit with code(%d)", __func__, status);
4486 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487}
4488
4489static char* adev_get_parameters(const struct audio_hw_device *dev,
4490 const char *keys)
4491{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004492 struct audio_device *adev = (struct audio_device *)dev;
4493 struct str_parms *reply = str_parms_create();
4494 struct str_parms *query = str_parms_create_str(keys);
4495 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304496 char value[256] = {0};
4497 int ret = 0;
4498
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004499 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004500 if (reply) {
4501 str_parms_destroy(reply);
4502 }
4503 if (query) {
4504 str_parms_destroy(query);
4505 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004506 ALOGE("adev_get_parameters: failed to create query or reply");
4507 return NULL;
4508 }
4509
Naresh Tannirud7205b62014-06-20 02:54:48 +05304510 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4511 sizeof(value));
4512 if (ret >=0) {
4513 int val = 1;
4514 pthread_mutex_lock(&adev->snd_card_status.lock);
4515 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4516 val = 0;
4517 pthread_mutex_unlock(&adev->snd_card_status.lock);
4518 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4519 goto exit;
4520 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004521
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004522 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004523 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004524 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004525 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304526 pthread_mutex_unlock(&adev->lock);
4527
Naresh Tannirud7205b62014-06-20 02:54:48 +05304528exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004529 str = str_parms_to_str(reply);
4530 str_parms_destroy(query);
4531 str_parms_destroy(reply);
4532
4533 ALOGV("%s: exit: returns - %s", __func__, str);
4534 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535}
4536
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004537static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538{
4539 return 0;
4540}
4541
4542static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4543{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004544 int ret;
4545 struct audio_device *adev = (struct audio_device *)dev;
4546 pthread_mutex_lock(&adev->lock);
4547 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004548 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004549 pthread_mutex_unlock(&adev->lock);
4550 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551}
4552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004553static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4554 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555{
4556 return -ENOSYS;
4557}
4558
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004559static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4560 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561{
4562 return -ENOSYS;
4563}
4564
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004565static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4566 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567{
4568 return -ENOSYS;
4569}
4570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004571static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4572 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573{
4574 return -ENOSYS;
4575}
4576
4577static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4578{
4579 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 pthread_mutex_lock(&adev->lock);
4582 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004583 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004584 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004585 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004586 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004587 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004588 adev->current_call_output = NULL;
4589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 }
4591 pthread_mutex_unlock(&adev->lock);
4592 return 0;
4593}
4594
4595static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4596{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004597 int ret;
4598
4599 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004600 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004601 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4602 pthread_mutex_unlock(&adev->lock);
4603
4604 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605}
4606
4607static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4608{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004609 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610 return 0;
4611}
4612
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004613static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 const struct audio_config *config)
4615{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004616 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004618 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4619 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620}
4621
4622static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004623 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624 audio_devices_t devices,
4625 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004626 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304627 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004628 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004629 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630{
4631 struct audio_device *adev = (struct audio_device *)dev;
4632 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004633 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004634 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004635 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304636 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304639 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4640 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304642 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643
4644 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004645
4646 if (!in) {
4647 ALOGE("failed to allocate input stream");
4648 return -ENOMEM;
4649 }
4650
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304651 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304652 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4653 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004654 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004655 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 in->stream.common.get_sample_rate = in_get_sample_rate;
4658 in->stream.common.set_sample_rate = in_set_sample_rate;
4659 in->stream.common.get_buffer_size = in_get_buffer_size;
4660 in->stream.common.get_channels = in_get_channels;
4661 in->stream.common.get_format = in_get_format;
4662 in->stream.common.set_format = in_set_format;
4663 in->stream.common.standby = in_standby;
4664 in->stream.common.dump = in_dump;
4665 in->stream.common.set_parameters = in_set_parameters;
4666 in->stream.common.get_parameters = in_get_parameters;
4667 in->stream.common.add_audio_effect = in_add_audio_effect;
4668 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4669 in->stream.set_gain = in_set_gain;
4670 in->stream.read = in_read;
4671 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4672
4673 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004674 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676 in->standby = 1;
4677 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004678 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004679 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004681 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004682 if (in->realtime) {
4683 in->config = pcm_config_audio_capture_rt;
4684 in->sample_rate = in->config.rate;
4685 in->af_period_multiplier = af_period_multiplier;
4686 } else {
4687 in->config = pcm_config_audio_capture;
4688 in->config.rate = config->sample_rate;
4689 in->sample_rate = config->sample_rate;
4690 in->af_period_multiplier = 1;
4691 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304692 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304694 /* restrict 24 bit capture for unprocessed source only
4695 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4696 */
4697 if (config->format == AUDIO_FORMAT_DEFAULT) {
4698 config->format = AUDIO_FORMAT_PCM_16_BIT;
4699 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4700 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4701 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4702 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4703 bool ret_error = false;
4704 in->bit_width = 24;
4705 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4706 from HAL is 24_packed and 8_24
4707 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4708 24_packed return error indicating supported format is 24_packed
4709 *> In case of any other source requesting 24 bit or float return error
4710 indicating format supported is 16 bit only.
4711
4712 on error flinger will retry with supported format passed
4713 */
4714 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4715 (source != AUDIO_SOURCE_CAMCORDER)) {
4716 config->format = AUDIO_FORMAT_PCM_16_BIT;
4717 if (config->sample_rate > 48000)
4718 config->sample_rate = 48000;
4719 ret_error = true;
4720 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4721 in->config.format = PCM_FORMAT_S24_3LE;
4722 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4723 in->config.format = PCM_FORMAT_S24_LE;
4724 } else {
4725 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4726 ret_error = true;
4727 }
4728
4729 if (ret_error) {
4730 ret = -EINVAL;
4731 goto err_open;
4732 }
4733 }
4734
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304735 in->usecase = USECASE_AUDIO_RECORD;
4736 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4737 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4738 is_low_latency = true;
4739#if LOW_LATENCY_CAPTURE_USE_CASE
4740 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4741#endif
4742 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4743 }
4744
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304745 pthread_mutex_lock(&adev->lock);
4746 if (in->usecase == USECASE_AUDIO_RECORD) {
4747 if (!(adev->pcm_record_uc_state) &&
4748 ((flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0)) {
4749 ALOGV("%s: pcm record usecase", __func__);
4750 adev->pcm_record_uc_state = 1;
4751 } else {
4752 /*
4753 * Assign default compress record use case, actual use case
4754 * assignment will happen later.
4755 */
4756 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
4757 ALOGV("%s: compress record usecase", __func__);
4758 }
4759 }
4760 pthread_mutex_unlock(&adev->lock);
4761
4762 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304763 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4764 (adev->mode != AUDIO_MODE_IN_CALL)) {
4765 ret = -EINVAL;
4766 goto err_open;
4767 }
4768
4769 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4770 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004771 if (config->sample_rate == 0)
4772 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4773 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4774 config->sample_rate != 8000) {
4775 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4776 ret = -EINVAL;
4777 goto err_open;
4778 }
4779 if (config->format == AUDIO_FORMAT_DEFAULT)
4780 config->format = AUDIO_FORMAT_PCM_16_BIT;
4781 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4782 config->format = AUDIO_FORMAT_PCM_16_BIT;
4783 ret = -EINVAL;
4784 goto err_open;
4785 }
4786
4787 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4788 in->config = pcm_config_afe_proxy_record;
4789 in->config.channels = channel_count;
4790 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304791 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304792 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4793 in, config, &channel_mask_updated)) {
4794 if (channel_mask_updated == true) {
4795 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4796 __func__, config->channel_mask);
4797 ret = -EINVAL;
4798 goto err_open;
4799 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304800 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004801 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004802 audio_extn_compr_cap_format_supported(config->format) &&
4803 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004804 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304805 } else if (audio_extn_cin_applicable_stream(in)) {
4806 ret = audio_extn_cin_configure_input_stream(in);
4807 if (ret)
4808 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004809 } else {
4810 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004811 if (!in->realtime) {
4812 in->format = config->format;
4813 frame_size = audio_stream_in_frame_size(&in->stream);
4814 buffer_size = get_input_buffer_size(config->sample_rate,
4815 config->format,
4816 channel_count,
4817 is_low_latency);
4818 in->config.period_size = buffer_size / frame_size;
4819 }
4820
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004821 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4822 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4823 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004824 (in->config.rate == 8000 || in->config.rate == 16000 ||
4825 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004826 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4827 voice_extn_compress_voip_open_input_stream(in);
4828 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004829 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304831 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4832 &adev->streams_input_cfg_list,
4833 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304834 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304835
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004836 /* This stream could be for sound trigger lab,
4837 get sound trigger pcm if present */
4838 audio_extn_sound_trigger_check_and_get_session(in);
4839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004841 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004842 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843
4844err_open:
4845 free(in);
4846 *stream_in = NULL;
4847 return ret;
4848}
4849
4850static void adev_close_input_stream(struct audio_hw_device *dev,
4851 struct audio_stream_in *stream)
4852{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004853 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004854 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004855 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304856
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304857 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004858
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304859 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004860 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304861
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004862 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304863 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004864 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304865 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004866 if (ret != 0)
4867 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4868 __func__, ret);
4869 } else
4870 in_standby(&stream->common);
4871
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004872 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004873 audio_extn_ssr_deinit();
4874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304876 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004877 audio_extn_compr_cap_format_supported(in->config.format))
4878 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304879
4880 if (in->usecase == USECASE_AUDIO_RECORD) {
4881 pthread_mutex_lock(&adev->lock);
4882 adev->pcm_record_uc_state = 0;
4883 pthread_mutex_unlock(&adev->lock);
4884 }
4885
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304886 if (audio_extn_cin_attached_usecase(in->usecase))
4887 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004888
Mingming Yinfd7607b2016-01-22 12:48:44 -08004889 if (in->is_st_session) {
4890 ALOGV("%s: sound trigger pcm stop lab", __func__);
4891 audio_extn_sound_trigger_stop_lab(in);
4892 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004893 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 return;
4895}
4896
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004897static int adev_dump(const audio_hw_device_t *device __unused,
4898 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899{
4900 return 0;
4901}
4902
4903static int adev_close(hw_device_t *device)
4904{
4905 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004906
4907 if (!adev)
4908 return 0;
4909
4910 pthread_mutex_lock(&adev_init_lock);
4911
4912 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004913 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004914 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304915 audio_extn_utils_release_streams_cfg_lists(
4916 &adev->streams_output_cfg_list,
4917 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304918 if (audio_extn_qaf_is_enabled())
4919 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004920 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004921 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004922 free(adev->snd_dev_ref_cnt);
4923 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004924 if (adev->adm_deinit)
4925 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304926 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004927 free(device);
4928 adev = NULL;
4929 }
4930 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932 return 0;
4933}
4934
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004935/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4936 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4937 * just that it _might_ work.
4938 */
4939static int period_size_is_plausible_for_low_latency(int period_size)
4940{
4941 switch (period_size) {
4942 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004943 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004944 case 240:
4945 case 320:
4946 case 480:
4947 return 1;
4948 default:
4949 return 0;
4950 }
4951}
4952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004953static int adev_open(const hw_module_t *module, const char *name,
4954 hw_device_t **device)
4955{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304956 int ret;
4957
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004958 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4960
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004961 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004962 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004963 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004964 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004965 ALOGD("%s: returning existing instance of adev", __func__);
4966 ALOGD("%s: exit", __func__);
4967 pthread_mutex_unlock(&adev_init_lock);
4968 return 0;
4969 }
4970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004971 adev = calloc(1, sizeof(struct audio_device));
4972
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004973 if (!adev) {
4974 pthread_mutex_unlock(&adev_init_lock);
4975 return -ENOMEM;
4976 }
4977
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004978 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4981 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4982 adev->device.common.module = (struct hw_module_t *)module;
4983 adev->device.common.close = adev_close;
4984
4985 adev->device.init_check = adev_init_check;
4986 adev->device.set_voice_volume = adev_set_voice_volume;
4987 adev->device.set_master_volume = adev_set_master_volume;
4988 adev->device.get_master_volume = adev_get_master_volume;
4989 adev->device.set_master_mute = adev_set_master_mute;
4990 adev->device.get_master_mute = adev_get_master_mute;
4991 adev->device.set_mode = adev_set_mode;
4992 adev->device.set_mic_mute = adev_set_mic_mute;
4993 adev->device.get_mic_mute = adev_get_mic_mute;
4994 adev->device.set_parameters = adev_set_parameters;
4995 adev->device.get_parameters = adev_get_parameters;
4996 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4997 adev->device.open_output_stream = adev_open_output_stream;
4998 adev->device.close_output_stream = adev_close_output_stream;
4999 adev->device.open_input_stream = adev_open_input_stream;
5000 adev->device.close_input_stream = adev_close_input_stream;
5001 adev->device.dump = adev_dump;
5002
5003 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005005 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005006 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005009 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005010 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005011 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005012 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005013 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005014 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005015 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005016 adev->offload_usecases_state = 0;
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305017 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305018 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305019 adev->perf_lock_opts[0] = 0x101;
5020 adev->perf_lock_opts[1] = 0x20E;
5021 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305022
5023 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5024 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005026 adev->platform = platform_init(adev);
5027 if (!adev->platform) {
5028 free(adev->snd_dev_ref_cnt);
5029 free(adev);
5030 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5031 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005032 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305033 pthread_mutex_destroy(&adev->lock);
5034 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005035 return -EINVAL;
5036 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005037
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305038 if (audio_extn_qaf_is_enabled()) {
5039 ret = audio_extn_qaf_init(adev);
5040 if (ret < 0) {
5041 free(adev);
5042 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5043 *device = NULL;
5044 pthread_mutex_unlock(&adev_init_lock);
5045 pthread_mutex_destroy(&adev->lock);
5046 return ret;
5047 }
5048
5049 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5050 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5051 }
5052
Naresh Tanniru4c630392014-05-12 01:05:52 +05305053 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5054
Eric Laurentc4aef752013-09-12 17:45:53 -07005055 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5056 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5057 if (adev->visualizer_lib == NULL) {
5058 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5059 } else {
5060 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5061 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005062 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005063 "visualizer_hal_start_output");
5064 adev->visualizer_stop_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_stop_output");
5067 }
5068 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305069 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005070 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005071 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005072 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005073
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005074 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5075 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5076 if (adev->offload_effects_lib == NULL) {
5077 ALOGE("%s: DLOPEN failed for %s", __func__,
5078 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5079 } else {
5080 ALOGV("%s: DLOPEN successful for %s", __func__,
5081 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5082 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305083 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005084 "offload_effects_bundle_hal_start_output");
5085 adev->offload_effects_stop_output =
5086 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5087 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005088 adev->offload_effects_set_hpx_state =
5089 (int (*)(bool))dlsym(adev->offload_effects_lib,
5090 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305091 adev->offload_effects_get_parameters =
5092 (void (*)(struct str_parms *, struct str_parms *))
5093 dlsym(adev->offload_effects_lib,
5094 "offload_effects_bundle_get_parameters");
5095 adev->offload_effects_set_parameters =
5096 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5097 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005098 }
5099 }
5100
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005101 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5102 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5103 if (adev->adm_lib == NULL) {
5104 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5105 } else {
5106 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5107 adev->adm_init = (adm_init_t)
5108 dlsym(adev->adm_lib, "adm_init");
5109 adev->adm_deinit = (adm_deinit_t)
5110 dlsym(adev->adm_lib, "adm_deinit");
5111 adev->adm_register_input_stream = (adm_register_input_stream_t)
5112 dlsym(adev->adm_lib, "adm_register_input_stream");
5113 adev->adm_register_output_stream = (adm_register_output_stream_t)
5114 dlsym(adev->adm_lib, "adm_register_output_stream");
5115 adev->adm_deregister_stream = (adm_deregister_stream_t)
5116 dlsym(adev->adm_lib, "adm_deregister_stream");
5117 adev->adm_request_focus = (adm_request_focus_t)
5118 dlsym(adev->adm_lib, "adm_request_focus");
5119 adev->adm_abandon_focus = (adm_abandon_focus_t)
5120 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005121 adev->adm_set_config = (adm_set_config_t)
5122 dlsym(adev->adm_lib, "adm_set_config");
5123 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5124 dlsym(adev->adm_lib, "adm_request_focus_v2");
5125 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5126 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5127 adev->adm_on_routing_change = (adm_on_routing_change_t)
5128 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005129 }
5130 }
5131
Mingming Yin514a8bc2014-07-29 15:22:21 -07005132 adev->bt_wb_speech_enabled = false;
5133
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005134 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135 *device = &adev->device.common;
5136
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305137 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5138 &adev->streams_output_cfg_list,
5139 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005140
Kiran Kandi910e1862013-10-29 13:29:42 -07005141 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005142
5143 char value[PROPERTY_VALUE_MAX];
5144 int trial;
5145 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5146 trial = atoi(value);
5147 if (period_size_is_plausible_for_low_latency(trial)) {
5148 pcm_config_low_latency.period_size = trial;
5149 pcm_config_low_latency.start_threshold = trial / 4;
5150 pcm_config_low_latency.avail_min = trial / 4;
5151 configured_low_latency_capture_period_size = trial;
5152 }
5153 }
5154 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5155 trial = atoi(value);
5156 if (period_size_is_plausible_for_low_latency(trial)) {
5157 configured_low_latency_capture_period_size = trial;
5158 }
5159 }
5160
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005161 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5162 af_period_multiplier = atoi(value);
5163 if (af_period_multiplier < 0)
5164 af_period_multiplier = 2;
5165 else if (af_period_multiplier > 4)
5166 af_period_multiplier = 4;
5167
5168 ALOGV("new period_multiplier = %d", af_period_multiplier);
5169 }
5170
vivek mehta446c3962015-09-14 10:57:35 -07005171 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005172 pthread_mutex_unlock(&adev_init_lock);
5173
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005174 if (adev->adm_init)
5175 adev->adm_data = adev->adm_init();
5176
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305177 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305178 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005179 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180 return 0;
5181}
5182
5183static struct hw_module_methods_t hal_module_methods = {
5184 .open = adev_open,
5185};
5186
5187struct audio_module HAL_MODULE_INFO_SYM = {
5188 .common = {
5189 .tag = HARDWARE_MODULE_TAG,
5190 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5191 .hal_api_version = HARDWARE_HAL_API_VERSION,
5192 .id = AUDIO_HARDWARE_MODULE_ID,
5193 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005194 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195 .methods = &hal_module_methods,
5196 },
5197};