blob: e1292c1d2e335f83f7832b087b3c35df4cad4250 [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 Jainc597d102016-12-12 10:31:34 +05301054 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1055 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1056 ((force_restart_session) ||
1057 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301058
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301059 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1060 __func__, use_case_table[usecase->id],
1061 platform_get_snd_device_name(usecase->out_snd_device));
1062 disable_audio_route(adev, usecase);
1063 switch_device[usecase->id] = true;
1064 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001065 }
1066 }
1067
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301068 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1069 num_uc_to_switch);
1070
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001072 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301074 /* Make sure the previous devices to be disabled first and then enable the
1075 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 list_for_each(node, &adev->usecase_list) {
1077 usecase = node_to_item(node, struct audio_usecase, list);
1078 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001079 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 }
1081 }
1082
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001083 list_for_each(node, &adev->usecase_list) {
1084 usecase = node_to_item(node, struct audio_usecase, list);
1085 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001087 }
1088 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001089
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090 /* Re-route all the usecases on the shared backend other than the
1091 specified usecase to new snd devices */
1092 list_for_each(node, &adev->usecase_list) {
1093 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301094 /* Update the out_snd_device only before enabling the audio route */
1095 if (switch_device[usecase->id]) {
1096 usecase->out_snd_device = snd_device;
1097 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301098 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301099 use_case_table[usecase->id],
1100 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301101 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301102 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 }
1104 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 }
1106}
1107
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301108static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001109 struct audio_usecase *uc_info,
1110 snd_device_t snd_device)
1111{
1112 struct listnode *node;
1113 struct audio_usecase *usecase;
1114 bool switch_device[AUDIO_USECASE_MAX];
1115 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301116 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001117
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301118 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1119 snd_device);
1120 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301121
1122 /*
1123 * Make sure out devices is checked against out codec backend device and
1124 * also in devices against in codec backend. Checking out device against in
1125 * codec backend or vice versa causes issues.
1126 */
1127 if (uc_info->type == PCM_CAPTURE)
1128 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001129 /*
1130 * This function is to make sure that all the active capture usecases
1131 * are always routed to the same input sound device.
1132 * For example, if audio-record and voice-call usecases are currently
1133 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1134 * is received for voice call then we have to make sure that audio-record
1135 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1136 * because of the limitation that two devices cannot be enabled
1137 * at the same time if they share the same backend.
1138 */
1139 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1140 switch_device[i] = false;
1141
1142 list_for_each(node, &adev->usecase_list) {
1143 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301144 /*
1145 * TODO: Enhance below condition to handle BT sco/USB multi recording
1146 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001147 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001148 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301149 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301150 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301151 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001152 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001153 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001154 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1155 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001156 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001157 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001158 switch_device[usecase->id] = true;
1159 num_uc_to_switch++;
1160 }
1161 }
1162
1163 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001164 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301166 /* Make sure the previous devices to be disabled first and then enable the
1167 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168 list_for_each(node, &adev->usecase_list) {
1169 usecase = node_to_item(node, struct audio_usecase, list);
1170 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001171 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001172 }
1173 }
1174
1175 list_for_each(node, &adev->usecase_list) {
1176 usecase = node_to_item(node, struct audio_usecase, list);
1177 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179 }
1180 }
1181
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001182 /* Re-route all the usecases on the shared backend other than the
1183 specified usecase to new snd devices */
1184 list_for_each(node, &adev->usecase_list) {
1185 usecase = node_to_item(node, struct audio_usecase, list);
1186 /* Update the in_snd_device only before enabling the audio route */
1187 if (switch_device[usecase->id] ) {
1188 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001189 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301190 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 }
1192 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001193 }
1194}
1195
Mingming Yin3a941d42016-02-17 18:08:05 -08001196static void reset_hdmi_sink_caps(struct stream_out *out) {
1197 int i = 0;
1198
1199 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1200 out->supported_channel_masks[i] = 0;
1201 }
1202 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1203 out->supported_formats[i] = 0;
1204 }
1205 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1206 out->supported_sample_rates[i] = 0;
1207 }
1208}
1209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001211static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212{
Mingming Yin3a941d42016-02-17 18:08:05 -08001213 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001214 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215
Mingming Yin3a941d42016-02-17 18:08:05 -08001216 reset_hdmi_sink_caps(out);
1217
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001218 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001219 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001220 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001221 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001222 }
1223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001226 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001227 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001228 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1229 case 6:
1230 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1231 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1232 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1233 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1234 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1235 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001236 break;
1237 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001238 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001239 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240 break;
1241 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001242
1243 // check channel format caps
1244 i = 0;
1245 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1246 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1247 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1248 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1249 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1250 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1251 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1252 }
1253
1254 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1255 ALOGV(":%s HDMI supports DTS format", __func__);
1256 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1257 }
1258
1259 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1260 ALOGV(":%s HDMI supports DTS HD format", __func__);
1261 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1262 }
1263
1264
1265 // check sample rate caps
1266 i = 0;
1267 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1268 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1269 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1270 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1271 }
1272 }
1273
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001274 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275}
1276
Alexy Josephb1379942016-01-29 15:49:38 -08001277audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001278 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001279{
1280 struct audio_usecase *usecase;
1281 struct listnode *node;
1282
1283 list_for_each(node, &adev->usecase_list) {
1284 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001285 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001286 ALOGV("%s: usecase id %d", __func__, usecase->id);
1287 return usecase->id;
1288 }
1289 }
1290 return USECASE_INVALID;
1291}
1292
Alexy Josephb1379942016-01-29 15:49:38 -08001293struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001294 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295{
1296 struct audio_usecase *usecase;
1297 struct listnode *node;
1298
1299 list_for_each(node, &adev->usecase_list) {
1300 usecase = node_to_item(node, struct audio_usecase, list);
1301 if (usecase->id == uc_id)
1302 return usecase;
1303 }
1304 return NULL;
1305}
1306
Dhananjay Kumard4833242016-10-06 22:09:12 +05301307struct stream_in *get_next_active_input(const struct audio_device *adev)
1308{
1309 struct audio_usecase *usecase;
1310 struct listnode *node;
1311
1312 list_for_each_reverse(node, &adev->usecase_list) {
1313 usecase = node_to_item(node, struct audio_usecase, list);
1314 if (usecase->type == PCM_CAPTURE)
1315 return usecase->stream.in;
1316 }
1317 return NULL;
1318}
1319
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301320/*
1321 * is a true native playback active
1322 */
1323bool audio_is_true_native_stream_active(struct audio_device *adev)
1324{
1325 bool active = false;
1326 int i = 0;
1327 struct listnode *node;
1328
1329 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1330 ALOGV("%s:napb: not in true mode or non hdphones device",
1331 __func__);
1332 active = false;
1333 goto exit;
1334 }
1335
1336 list_for_each(node, &adev->usecase_list) {
1337 struct audio_usecase *uc;
1338 uc = node_to_item(node, struct audio_usecase, list);
1339 struct stream_out *curr_out =
1340 (struct stream_out*) uc->stream.out;
1341
1342 if (curr_out && PCM_PLAYBACK == uc->type) {
1343 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1344 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1345 uc->id, curr_out->sample_rate,
1346 curr_out->bit_width,
1347 platform_get_snd_device_name(uc->out_snd_device));
1348
1349 if (is_offload_usecase(uc->id) &&
1350 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1351 active = true;
1352 ALOGD("%s:napb:native stream detected", __func__);
1353 }
1354 }
1355 }
1356exit:
1357 return active;
1358}
1359
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301360/*
1361 * if native DSD playback active
1362 */
1363bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1364{
1365 bool active = false;
1366 struct listnode *node = NULL;
1367 struct audio_usecase *uc = NULL;
1368 struct stream_out *curr_out = NULL;
1369
1370 list_for_each(node, &adev->usecase_list) {
1371 uc = node_to_item(node, struct audio_usecase, list);
1372 curr_out = (struct stream_out*) uc->stream.out;
1373
1374 if (curr_out && PCM_PLAYBACK == uc->type &&
1375 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1376 active = true;
1377 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301378 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301379 }
1380 }
1381 return active;
1382}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301383
1384static bool force_device_switch(struct audio_usecase *usecase)
1385{
1386 bool ret = false;
1387 bool is_it_true_mode = false;
1388
1389 if (is_offload_usecase(usecase->id) &&
1390 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001391 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1392 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1393 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301394 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1395 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1396 (!is_it_true_mode && adev->native_playback_enabled)){
1397 ret = true;
1398 ALOGD("napb: time to toggle native mode");
1399 }
1400 }
1401
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301402 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301403 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1404 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301405 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001406 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301407 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301408 ALOGD("Force a2dp device switch to update new encoder config");
1409 ret = true;
1410 }
1411
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301412 return ret;
1413}
1414
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001415int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001417 snd_device_t out_snd_device = SND_DEVICE_NONE;
1418 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001419 struct audio_usecase *usecase = NULL;
1420 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001421 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001422 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001423 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301426 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1427
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001428 usecase = get_usecase_from_list(adev, uc_id);
1429 if (usecase == NULL) {
1430 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1431 return -EINVAL;
1432 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001434 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001435 (usecase->type == VOIP_CALL) ||
1436 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301437 if(usecase->stream.out == NULL) {
1438 ALOGE("%s: stream.out is NULL", __func__);
1439 return -EINVAL;
1440 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001441 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001442 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001443 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 usecase->devices = usecase->stream.out->devices;
1445 } else {
1446 /*
1447 * If the voice call is active, use the sound devices of voice call usecase
1448 * so that it would not result any device switch. All the usecases will
1449 * be switched to new device when select_devices() is called for voice call
1450 * usecase. This is to avoid switching devices for voice call when
1451 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001452 * choose voice call device only if the use case device is
1453 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001455 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001456 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001457 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001458 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1459 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301460 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1461 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001462 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 in_snd_device = vc_usecase->in_snd_device;
1464 out_snd_device = vc_usecase->out_snd_device;
1465 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001466 } else if (voice_extn_compress_voip_is_active(adev)) {
1467 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001468 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001469 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1470 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001471 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001472 in_snd_device = voip_usecase->in_snd_device;
1473 out_snd_device = voip_usecase->out_snd_device;
1474 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001475 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001476 hfp_ucid = audio_extn_hfp_get_usecase();
1477 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001478 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001479 in_snd_device = hfp_usecase->in_snd_device;
1480 out_snd_device = hfp_usecase->out_snd_device;
1481 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 }
1483 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301484 if (usecase->stream.out == NULL) {
1485 ALOGE("%s: stream.out is NULL", __func__);
1486 return -EINVAL;
1487 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488 usecase->devices = usecase->stream.out->devices;
1489 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001490 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001491 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001492 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001493 if (usecase->stream.out == adev->primary_output &&
1494 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001495 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001496 select_devices(adev, adev->active_input->usecase);
1497 }
1498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301500 if (usecase->stream.in == NULL) {
1501 ALOGE("%s: stream.in is NULL", __func__);
1502 return -EINVAL;
1503 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001504 usecase->devices = usecase->stream.in->device;
1505 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001506 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001507 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001508 if (adev->active_input &&
1509 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301510 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1511 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1512 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001513 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001514 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001515 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1516 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001517 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001518 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001519 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 }
1521 }
1522
1523 if (out_snd_device == usecase->out_snd_device &&
1524 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301525
1526 if (!force_device_switch(usecase))
1527 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 }
1529
sangwoobc677242013-08-08 16:53:43 +09001530 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001531 out_snd_device, platform_get_snd_device_name(out_snd_device),
1532 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 /*
1535 * Limitation: While in call, to do a device switch we need to disable
1536 * and enable both RX and TX devices though one of them is same as current
1537 * device.
1538 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001539 if ((usecase->type == VOICE_CALL) &&
1540 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1541 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001542 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001543 }
1544
1545 if (((usecase->type == VOICE_CALL) ||
1546 (usecase->type == VOIP_CALL)) &&
1547 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1548 /* Disable sidetone only if voice/voip call already exists */
1549 if (voice_is_call_state_active(adev) ||
1550 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001551 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001552
1553 /* Disable aanc only if voice call exists */
1554 if (voice_is_call_state_active(adev))
1555 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001556 }
1557
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 /* Disable current sound devices */
1559 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001560 disable_audio_route(adev, usecase);
1561 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562 }
1563
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001565 disable_audio_route(adev, usecase);
1566 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 }
1568
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001569 /* Applicable only on the targets that has external modem.
1570 * New device information should be sent to modem before enabling
1571 * the devices to reduce in-call device switch time.
1572 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001573 if ((usecase->type == VOICE_CALL) &&
1574 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1575 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001576 status = platform_switch_voice_call_enable_device_config(adev->platform,
1577 out_snd_device,
1578 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001579 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001580
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001581 /* Enable new sound devices */
1582 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001583 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301584 if (platform_check_codec_asrc_support(adev->platform))
1585 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001586 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 }
1588
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001589 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301590 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001591 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001592 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001593
Avinash Vaish71a8b972014-07-24 15:36:33 +05301594 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001595 status = platform_switch_voice_call_device_post(adev->platform,
1596 out_snd_device,
1597 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301598 enable_audio_route_for_voice_usecases(adev, usecase);
1599 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001600
sangwoo170731f2013-06-08 15:36:36 +09001601 usecase->in_snd_device = in_snd_device;
1602 usecase->out_snd_device = out_snd_device;
1603
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301604 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1605 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301606 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001607 if ((24 == usecase->stream.out->bit_width) &&
1608 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1609 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1610 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1611 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1612 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1613 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1614 /*
1615 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1616 * configured device sample rate, if not update the COPP rate to be equal to the
1617 * device sample rate, else open COPP at stream sample rate
1618 */
1619 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1620 usecase->stream.out->sample_rate,
1621 &usecase->stream.out->app_type_cfg.sample_rate);
1622 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1623 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1624 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1625 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1626 }
1627
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001628 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001629 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001630 audio_extn_gef_notify_device_config(
1631 usecase->stream.out->devices,
1632 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001633 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001634 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001635 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301636 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001637 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001638
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001639 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001640 /* Enable aanc only if voice call exists */
1641 if (voice_is_call_state_active(adev))
1642 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1643
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001644 /* Enable sidetone only if other voice/voip call already exists */
1645 if (voice_is_call_state_active(adev) ||
1646 voice_extn_compress_voip_is_started(adev))
1647 voice_set_sidetone(adev, out_snd_device, true);
1648 }
1649
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001650 /* Applicable only on the targets that has external modem.
1651 * Enable device command should be sent to modem only after
1652 * enabling voice call mixer controls
1653 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001654 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001655 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1656 out_snd_device,
1657 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301658 ALOGD("%s: done",__func__);
1659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 return status;
1661}
1662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663static int stop_input_stream(struct stream_in *in)
1664{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301665 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666 struct audio_usecase *uc_info;
1667 struct audio_device *adev = in->dev;
1668
Eric Laurent994a6932013-07-17 11:51:42 -07001669 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 uc_info = get_usecase_from_list(adev, in->usecase);
1672 if (uc_info == NULL) {
1673 ALOGE("%s: Could not find the usecase (%d) in the list",
1674 __func__, in->usecase);
1675 return -EINVAL;
1676 }
1677
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001678 /* Close in-call recording streams */
1679 voice_check_and_stop_incall_rec_usecase(adev, in);
1680
Eric Laurent150dbfe2013-02-27 14:31:02 -08001681 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001682 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683
1684 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001685 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001687 list_remove(&uc_info->list);
1688 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001690 adev->active_input = get_next_active_input(adev);
1691
Eric Laurent994a6932013-07-17 11:51:42 -07001692 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 return ret;
1694}
1695
1696int start_input_stream(struct stream_in *in)
1697{
1698 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001699 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 struct audio_usecase *uc_info;
1701 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301702 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703
Mingming Yin2664a5b2015-09-03 10:53:11 -07001704 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1705 if (get_usecase_from_list(adev, usecase) == NULL)
1706 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301707 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1708 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001709
Naresh Tanniru80659832014-06-04 18:17:56 +05301710
1711 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301712 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301713 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301714 goto error_config;
1715 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301716
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001717 /* Check if source matches incall recording usecase criteria */
1718 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1719 if (ret)
1720 goto error_config;
1721 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001722 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1723
1724 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1725 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1726 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001727 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001728 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001729
Eric Laurentb23d5282013-05-14 15:27:20 -07001730 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 if (in->pcm_device_id < 0) {
1732 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1733 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001734 ret = -EINVAL;
1735 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001737
1738 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001740
1741 if (!uc_info) {
1742 ret = -ENOMEM;
1743 goto error_config;
1744 }
1745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 uc_info->id = in->usecase;
1747 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001748 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 uc_info->devices = in->device;
1750 uc_info->in_snd_device = SND_DEVICE_NONE;
1751 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001753 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301754 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1755 adev->perf_lock_opts,
1756 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001757 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301759 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1760 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001761
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301762 if (audio_extn_cin_attached_usecase(in->usecase)) {
1763 ret = audio_extn_cin_start_input_stream(in);
1764 if (ret)
1765 goto error_open;
1766 else
1767 goto done_open;
1768 }
1769
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001770 unsigned int flags = PCM_IN;
1771 unsigned int pcm_open_retry_count = 0;
1772
1773 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1774 flags |= PCM_MMAP | PCM_NOIRQ;
1775 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001776 } else if (in->realtime) {
1777 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001778 }
1779
1780 while (1) {
1781 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1782 flags, &in->config);
1783 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1784 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1785 if (in->pcm != NULL) {
1786 pcm_close(in->pcm);
1787 in->pcm = NULL;
1788 }
1789 if (pcm_open_retry_count-- == 0) {
1790 ret = -EIO;
1791 goto error_open;
1792 }
1793 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1794 continue;
1795 }
1796 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001798
1799 ALOGV("%s: pcm_prepare", __func__);
1800 ret = pcm_prepare(in->pcm);
1801 if (ret < 0) {
1802 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1803 pcm_close(in->pcm);
1804 in->pcm = NULL;
1805 goto error_open;
1806 }
1807
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001808 register_in_stream(in);
1809 if (in->realtime) {
1810 ret = pcm_start(in->pcm);
1811 if (ret < 0)
1812 goto error_open;
1813 }
1814
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301815done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301816 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001817 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001818
Eric Laurentc8400632013-02-14 19:04:54 -08001819 return ret;
1820
1821error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301822 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001824error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301825 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301826 /*
1827 * sleep 50ms to allow sufficient time for kernel
1828 * drivers to recover incases like SSR.
1829 */
1830 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001832
1833 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834}
1835
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001836void lock_input_stream(struct stream_in *in)
1837{
1838 pthread_mutex_lock(&in->pre_lock);
1839 pthread_mutex_lock(&in->lock);
1840 pthread_mutex_unlock(&in->pre_lock);
1841}
1842
1843void lock_output_stream(struct stream_out *out)
1844{
1845 pthread_mutex_lock(&out->pre_lock);
1846 pthread_mutex_lock(&out->lock);
1847 pthread_mutex_unlock(&out->pre_lock);
1848}
1849
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850/* must be called with out->lock locked */
1851static int send_offload_cmd_l(struct stream_out* out, int command)
1852{
1853 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1854
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001855 if (!cmd) {
1856 ALOGE("failed to allocate mem for command 0x%x", command);
1857 return -ENOMEM;
1858 }
1859
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001860 ALOGVV("%s %d", __func__, command);
1861
1862 cmd->cmd = command;
1863 list_add_tail(&out->offload_cmd_list, &cmd->node);
1864 pthread_cond_signal(&out->offload_cond);
1865 return 0;
1866}
1867
1868/* must be called iwth out->lock locked */
1869static void stop_compressed_output_l(struct stream_out *out)
1870{
1871 out->offload_state = OFFLOAD_STATE_IDLE;
1872 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001873 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001874 if (out->compr != NULL) {
1875 compress_stop(out->compr);
1876 while (out->offload_thread_blocked) {
1877 pthread_cond_wait(&out->cond, &out->lock);
1878 }
1879 }
1880}
1881
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001882bool is_offload_usecase(audio_usecase_t uc_id)
1883{
1884 unsigned int i;
1885 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1886 if (uc_id == offload_usecases[i])
1887 return true;
1888 }
1889 return false;
1890}
1891
vivek mehta446c3962015-09-14 10:57:35 -07001892static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001893{
vivek mehta446c3962015-09-14 10:57:35 -07001894 audio_usecase_t ret_uc = USECASE_INVALID;
1895 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001896 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001897 if (!adev->multi_offload_enable) {
1898 if (is_direct_pcm)
1899 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1900 else
1901 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001902
vivek mehta446c3962015-09-14 10:57:35 -07001903 pthread_mutex_lock(&adev->lock);
1904 if (get_usecase_from_list(adev, ret_uc) != NULL)
1905 ret_uc = USECASE_INVALID;
1906 pthread_mutex_unlock(&adev->lock);
1907
1908 return ret_uc;
1909 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001910
1911 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001912 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1913 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1914 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1915 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001916 break;
1917 }
1918 }
vivek mehta446c3962015-09-14 10:57:35 -07001919
1920 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1921 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001922}
1923
1924static void free_offload_usecase(struct audio_device *adev,
1925 audio_usecase_t uc_id)
1926{
vivek mehta446c3962015-09-14 10:57:35 -07001927 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001928 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001929
1930 if (!adev->multi_offload_enable)
1931 return;
1932
1933 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1934 if (offload_usecases[offload_uc_index] == uc_id) {
1935 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001936 break;
1937 }
1938 }
1939 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1940}
1941
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942static void *offload_thread_loop(void *context)
1943{
1944 struct stream_out *out = (struct stream_out *) context;
1945 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001946 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001947
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1949 set_sched_policy(0, SP_FOREGROUND);
1950 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1951
1952 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001953 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001954 for (;;) {
1955 struct offload_cmd *cmd = NULL;
1956 stream_callback_event_t event;
1957 bool send_callback = false;
1958
1959 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1960 __func__, list_empty(&out->offload_cmd_list),
1961 out->offload_state);
1962 if (list_empty(&out->offload_cmd_list)) {
1963 ALOGV("%s SLEEPING", __func__);
1964 pthread_cond_wait(&out->offload_cond, &out->lock);
1965 ALOGV("%s RUNNING", __func__);
1966 continue;
1967 }
1968
1969 item = list_head(&out->offload_cmd_list);
1970 cmd = node_to_item(item, struct offload_cmd, node);
1971 list_remove(item);
1972
1973 ALOGVV("%s STATE %d CMD %d out->compr %p",
1974 __func__, out->offload_state, cmd->cmd, out->compr);
1975
1976 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1977 free(cmd);
1978 break;
1979 }
1980
1981 if (out->compr == NULL) {
1982 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001983 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 pthread_cond_signal(&out->cond);
1985 continue;
1986 }
1987 out->offload_thread_blocked = true;
1988 pthread_mutex_unlock(&out->lock);
1989 send_callback = false;
1990 switch(cmd->cmd) {
1991 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001992 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001994 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001995 send_callback = true;
1996 event = STREAM_CBK_EVENT_WRITE_READY;
1997 break;
1998 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001999 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302000 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002001 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302002 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002003 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302004 if (ret < 0)
2005 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302006 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302007 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002008 compress_drain(out->compr);
2009 else
2010 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302011 if (ret != -ENETRESET) {
2012 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302013 pthread_mutex_lock(&out->lock);
2014 out->send_new_metadata = 1;
2015 out->send_next_track_params = true;
2016 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302017 event = STREAM_CBK_EVENT_DRAIN_READY;
2018 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2019 } else
2020 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021 break;
2022 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002023 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002025 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 send_callback = true;
2027 event = STREAM_CBK_EVENT_DRAIN_READY;
2028 break;
2029 default:
2030 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2031 break;
2032 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002033 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002034 out->offload_thread_blocked = false;
2035 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002036 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002037 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002039 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002040 free(cmd);
2041 }
2042
2043 pthread_cond_signal(&out->cond);
2044 while (!list_empty(&out->offload_cmd_list)) {
2045 item = list_head(&out->offload_cmd_list);
2046 list_remove(item);
2047 free(node_to_item(item, struct offload_cmd, node));
2048 }
2049 pthread_mutex_unlock(&out->lock);
2050
2051 return NULL;
2052}
2053
2054static int create_offload_callback_thread(struct stream_out *out)
2055{
2056 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2057 list_init(&out->offload_cmd_list);
2058 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2059 offload_thread_loop, out);
2060 return 0;
2061}
2062
2063static int destroy_offload_callback_thread(struct stream_out *out)
2064{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002065 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066 stop_compressed_output_l(out);
2067 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2068
2069 pthread_mutex_unlock(&out->lock);
2070 pthread_join(out->offload_thread, (void **) NULL);
2071 pthread_cond_destroy(&out->offload_cond);
2072
2073 return 0;
2074}
2075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076static int stop_output_stream(struct stream_out *out)
2077{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302078 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 struct audio_usecase *uc_info;
2080 struct audio_device *adev = out->dev;
2081
Eric Laurent994a6932013-07-17 11:51:42 -07002082 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084 uc_info = get_usecase_from_list(adev, out->usecase);
2085 if (uc_info == NULL) {
2086 ALOGE("%s: Could not find the usecase (%d) in the list",
2087 __func__, out->usecase);
2088 return -EINVAL;
2089 }
2090
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002091 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302092 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002093 if (adev->visualizer_stop_output != NULL)
2094 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002095
2096 audio_extn_dts_remove_state_notifier_node(out->usecase);
2097
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002098 if (adev->offload_effects_stop_output != NULL)
2099 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2100 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002101
Eric Laurent150dbfe2013-02-27 14:31:02 -08002102 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002103 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002104
2105 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002106 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002108 list_remove(&uc_info->list);
2109 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002111 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302112 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002113 ALOGV("Disable passthrough , reset mixer to pcm");
2114 /* NO_PASSTHROUGH */
2115 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002116 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002117 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2118 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002119
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302120 /* Must be called after removing the usecase from list */
2121 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302122 audio_extn_keep_alive_start();
2123
Eric Laurent994a6932013-07-17 11:51:42 -07002124 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 return ret;
2126}
2127
2128int start_output_stream(struct stream_out *out)
2129{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 struct audio_usecase *uc_info;
2132 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302133 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002135 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2136 ret = -EINVAL;
2137 goto error_config;
2138 }
2139
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302140 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2141 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2142 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302143
Naresh Tanniru80659832014-06-04 18:17:56 +05302144 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302145 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302146 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302147 goto error_config;
2148 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302149
Eric Laurentb23d5282013-05-14 15:27:20 -07002150 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 if (out->pcm_device_id < 0) {
2152 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2153 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002154 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002155 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 }
2157
2158 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002159
2160 if (!uc_info) {
2161 ret = -ENOMEM;
2162 goto error_config;
2163 }
2164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 uc_info->id = out->usecase;
2166 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002167 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002168 uc_info->devices = out->devices;
2169 uc_info->in_snd_device = SND_DEVICE_NONE;
2170 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002171 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302173 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2174 adev->perf_lock_opts,
2175 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302176
2177 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2178 audio_extn_keep_alive_stop();
2179 if (audio_extn_passthru_is_enabled() &&
2180 audio_extn_passthru_is_passthrough_stream(out)) {
2181 audio_extn_passthru_on_start(out);
2182 audio_extn_passthru_update_stream_configuration(adev, out);
2183 }
2184 }
2185
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002186 select_devices(adev, out->usecase);
2187
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002188 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2189 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002190 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002191 unsigned int flags = PCM_OUT;
2192 unsigned int pcm_open_retry_count = 0;
2193 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2194 flags |= PCM_MMAP | PCM_NOIRQ;
2195 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002196 } else if (out->realtime) {
2197 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002198 } else
2199 flags |= PCM_MONOTONIC;
2200
2201 while (1) {
2202 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2203 flags, &out->config);
2204 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2205 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2206 if (out->pcm != NULL) {
2207 pcm_close(out->pcm);
2208 out->pcm = NULL;
2209 }
2210 if (pcm_open_retry_count-- == 0) {
2211 ret = -EIO;
2212 goto error_open;
2213 }
2214 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2215 continue;
2216 }
2217 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002219
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002220 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2221 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002222
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002223 ALOGV("%s: pcm_prepare", __func__);
2224 if (pcm_is_ready(out->pcm)) {
2225 ret = pcm_prepare(out->pcm);
2226 if (ret < 0) {
2227 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2228 pcm_close(out->pcm);
2229 out->pcm = NULL;
2230 goto error_open;
2231 }
2232 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002233 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002234 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2235 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002237 out->compr = compress_open(adev->snd_card,
2238 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 COMPRESS_IN, &out->compr_config);
2240 if (out->compr && !is_compress_ready(out->compr)) {
2241 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2242 compress_close(out->compr);
2243 out->compr = NULL;
2244 ret = -EIO;
2245 goto error_open;
2246 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302247 /* compress_open sends params of the track, so reset the flag here */
2248 out->is_compr_metadata_avail = false;
2249
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002250 if (out->offload_callback)
2251 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002252
Fred Oh3f43e742015-03-04 18:42:34 -08002253 /* Since small bufs uses blocking writes, a write will be blocked
2254 for the default max poll time (20s) in the event of an SSR.
2255 Reduce the poll time to observe and deal with SSR faster.
2256 */
Ashish Jain5106d362016-05-11 19:23:33 +05302257 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002258 compress_set_max_poll_wait(out->compr, 1000);
2259 }
2260
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002261 audio_extn_dts_create_state_notifier_node(out->usecase);
2262 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2263 popcount(out->channel_mask),
2264 out->playback_started);
2265
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002266#ifdef DS1_DOLBY_DDP_ENABLED
2267 if (audio_extn_is_dolby_format(out->format))
2268 audio_extn_dolby_send_ddp_endp_params(adev);
2269#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302270 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002271 if (adev->visualizer_start_output != NULL)
2272 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2273 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302274 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002275 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002278
2279 if (ret == 0) {
2280 register_out_stream(out);
2281 if (out->realtime) {
2282 ret = pcm_start(out->pcm);
2283 if (ret < 0)
2284 goto error_open;
2285 }
2286 }
2287
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302288 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002289 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002290
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002291 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302293 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002295error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302296 /*
2297 * sleep 50ms to allow sufficient time for kernel
2298 * drivers to recover incases like SSR.
2299 */
2300 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002301 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302}
2303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304static int check_input_parameters(uint32_t sample_rate,
2305 audio_format_t format,
2306 int channel_count)
2307{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002308 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302310 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2311 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2312 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002313 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302314 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002315
2316 switch (channel_count) {
2317 case 1:
2318 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302319 case 3:
2320 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002321 case 6:
2322 break;
2323 default:
2324 ret = -EINVAL;
2325 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326
2327 switch (sample_rate) {
2328 case 8000:
2329 case 11025:
2330 case 12000:
2331 case 16000:
2332 case 22050:
2333 case 24000:
2334 case 32000:
2335 case 44100:
2336 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302337 case 96000:
2338 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339 break;
2340 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002341 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342 }
2343
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345}
2346
2347static size_t get_input_buffer_size(uint32_t sample_rate,
2348 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002349 int channel_count,
2350 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351{
2352 size_t size = 0;
2353
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002354 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2355 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002357 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002358 if (is_low_latency)
2359 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302360
2361 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002363 /* make sure the size is multiple of 32 bytes
2364 * At 48 kHz mono 16-bit PCM:
2365 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2366 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2367 */
2368 size += 0x1f;
2369 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002370
2371 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372}
2373
Ashish Jain058165c2016-09-28 23:18:48 +05302374static size_t get_output_period_size(uint32_t sample_rate,
2375 audio_format_t format,
2376 int channel_count,
2377 int duration /*in millisecs*/)
2378{
2379 size_t size = 0;
2380 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2381
2382 if ((duration == 0) || (sample_rate == 0) ||
2383 (bytes_per_sample == 0) || (channel_count == 0)) {
2384 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2385 bytes_per_sample, channel_count);
2386 return -EINVAL;
2387 }
2388
2389 size = (sample_rate *
2390 duration *
2391 bytes_per_sample *
2392 channel_count) / 1000;
2393 /*
2394 * To have same PCM samples for all channels, the buffer size requires to
2395 * be multiple of (number of channels * bytes per sample)
2396 * For writes to succeed, the buffer must be written at address which is multiple of 32
2397 */
2398 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2399
2400 return (size/(channel_count * bytes_per_sample));
2401}
2402
Ashish Jain5106d362016-05-11 19:23:33 +05302403static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2404{
2405 uint64_t actual_frames_rendered = 0;
2406 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2407
2408 /* This adjustment accounts for buffering after app processor.
2409 * It is based on estimated DSP latency per use case, rather than exact.
2410 */
2411 int64_t platform_latency = platform_render_latency(out->usecase) *
2412 out->sample_rate / 1000000LL;
2413
2414 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2415 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2416 * hence only estimate.
2417 */
2418 int64_t signed_frames = out->written - kernel_buffer_size;
2419
2420 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2421
2422 if (signed_frames > 0)
2423 actual_frames_rendered = signed_frames;
2424
2425 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2426 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2427 (long long int)out->written, (int)kernel_buffer_size,
2428 audio_bytes_per_sample(out->compr_config.codec->format),
2429 popcount(out->channel_mask));
2430
2431 return actual_frames_rendered;
2432}
2433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2435{
2436 struct stream_out *out = (struct stream_out *)stream;
2437
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002438 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439}
2440
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002441static int out_set_sample_rate(struct audio_stream *stream __unused,
2442 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443{
2444 return -ENOSYS;
2445}
2446
2447static size_t out_get_buffer_size(const struct audio_stream *stream)
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002451 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002453 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2454 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302455 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302456 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002458 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002459 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460}
2461
2462static uint32_t out_get_channels(const struct audio_stream *stream)
2463{
2464 struct stream_out *out = (struct stream_out *)stream;
2465
2466 return out->channel_mask;
2467}
2468
2469static audio_format_t out_get_format(const struct audio_stream *stream)
2470{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 struct stream_out *out = (struct stream_out *)stream;
2472
2473 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474}
2475
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002476static int out_set_format(struct audio_stream *stream __unused,
2477 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478{
2479 return -ENOSYS;
2480}
2481
2482static int out_standby(struct audio_stream *stream)
2483{
2484 struct stream_out *out = (struct stream_out *)stream;
2485 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302487 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2488 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002490 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002492 if (adev->adm_deregister_stream)
2493 adev->adm_deregister_stream(adev->adm_data, out->handle);
2494
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002495 if (is_offload_usecase(out->usecase))
2496 stop_compressed_output_l(out);
2497
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002498 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002500 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2501 voice_extn_compress_voip_close_output_stream(stream);
2502 pthread_mutex_unlock(&adev->lock);
2503 pthread_mutex_unlock(&out->lock);
2504 ALOGD("VOIP output entered standby");
2505 return 0;
2506 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 if (out->pcm) {
2508 pcm_close(out->pcm);
2509 out->pcm = NULL;
2510 }
2511 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002512 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302513 out->send_next_track_params = false;
2514 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002515 out->gapless_mdata.encoder_delay = 0;
2516 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517 if (out->compr != NULL) {
2518 compress_close(out->compr);
2519 out->compr = NULL;
2520 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 }
2525 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302526 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 return 0;
2528}
2529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002530static int out_dump(const struct audio_stream *stream __unused,
2531 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532{
2533 return 0;
2534}
2535
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002536static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2537{
2538 int ret = 0;
2539 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002540
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002541 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002542 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002543 return -EINVAL;
2544 }
2545
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302546 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002547
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002548 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2549 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302550 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002551 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002552 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2553 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302554 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002555 }
2556
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002557 ALOGV("%s new encoder delay %u and padding %u", __func__,
2558 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2559
2560 return 0;
2561}
2562
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002563static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2564{
2565 return out == adev->primary_output || out == adev->voice_tx_output;
2566}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2569{
2570 struct stream_out *out = (struct stream_out *)stream;
2571 struct audio_device *adev = out->dev;
2572 struct str_parms *parms;
2573 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002574 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575
sangwoobc677242013-08-08 16:53:43 +09002576 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002577 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302579 if (!parms)
2580 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002581 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2582 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002584 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002585 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002587 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002588 * When HDMI cable is unplugged the music playback is paused and
2589 * the policy manager sends routing=0. But the audioflinger continues
2590 * to write data until standby time (3sec). As the HDMI core is
2591 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002592 * Avoid this by routing audio to speaker until standby.
2593 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002594 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2595 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302596 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002597 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2598 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002599 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302600 /*
2601 * When A2DP is disconnected the
2602 * music playback is paused and the policy manager sends routing=0
2603 * But the audioflingercontinues to write data until standby time
2604 * (3sec). As BT is turned off, the write gets blocked.
2605 * Avoid this by routing audio to speaker until standby.
2606 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002607 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302608 (val == AUDIO_DEVICE_NONE)) {
2609 val = AUDIO_DEVICE_OUT_SPEAKER;
2610 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302611 /* To avoid a2dp to sco overlapping force route BT usecases
2612 * to speaker based on Phone state
2613 */
Ashish Jainc597d102016-12-12 10:31:34 +05302614 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2615 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2616 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2617 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302618 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2619 (adev->mode == AUDIO_MODE_IN_CALL))) {
2620 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2621 val = AUDIO_DEVICE_OUT_SPEAKER;
2622 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002623 /*
2624 * select_devices() call below switches all the usecases on the same
2625 * backend to the new device. Refer to check_usecases_codec_backend() in
2626 * the select_devices(). But how do we undo this?
2627 *
2628 * For example, music playback is active on headset (deep-buffer usecase)
2629 * and if we go to ringtones and select a ringtone, low-latency usecase
2630 * will be started on headset+speaker. As we can't enable headset+speaker
2631 * and headset devices at the same time, select_devices() switches the music
2632 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2633 * So when the ringtone playback is completed, how do we undo the same?
2634 *
2635 * We are relying on the out_set_parameters() call on deep-buffer output,
2636 * once the ringtone playback is ended.
2637 * NOTE: We should not check if the current devices are same as new devices.
2638 * Because select_devices() must be called to switch back the music
2639 * playback to headset.
2640 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002641 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002642 audio_devices_t new_dev = val;
2643 bool same_dev = out->devices == new_dev;
2644 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002645
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002646 if (output_drives_call(adev, out)) {
2647 if(!voice_is_in_call(adev)) {
2648 if (adev->mode == AUDIO_MODE_IN_CALL) {
2649 adev->current_call_output = out;
2650 ret = voice_start_call(adev);
2651 }
2652 } else {
2653 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002654 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002655 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002656 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002657
2658 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002659 if (!same_dev) {
2660 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302661 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2662 adev->perf_lock_opts,
2663 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002664 if (adev->adm_on_routing_change)
2665 adev->adm_on_routing_change(adev->adm_data,
2666 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002667 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002668 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302669 if (!same_dev)
2670 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002671 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002672 }
2673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002675 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002677
2678 if (out == adev->primary_output) {
2679 pthread_mutex_lock(&adev->lock);
2680 audio_extn_set_parameters(adev, parms);
2681 pthread_mutex_unlock(&adev->lock);
2682 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002683 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002684 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002685 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002686
2687 audio_extn_dts_create_state_notifier_node(out->usecase);
2688 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2689 popcount(out->channel_mask),
2690 out->playback_started);
2691
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002692 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002693 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002694
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302695 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2696 if (err >= 0) {
2697 strlcpy(out->profile, value, sizeof(out->profile));
2698 ALOGV("updating stream profile with value '%s'", out->profile);
2699 lock_output_stream(out);
2700 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2701 &adev->streams_output_cfg_list,
2702 out->devices, out->flags, out->format,
2703 out->sample_rate, out->bit_width,
2704 out->channel_mask, out->profile,
2705 &out->app_type_cfg);
2706 pthread_mutex_unlock(&out->lock);
2707 }
2708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302710error:
Eric Laurent994a6932013-07-17 11:51:42 -07002711 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 return ret;
2713}
2714
2715static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2716{
2717 struct stream_out *out = (struct stream_out *)stream;
2718 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002719 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 char value[256];
2721 struct str_parms *reply = str_parms_create();
2722 size_t i, j;
2723 int ret;
2724 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002725
2726 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002727 if (reply) {
2728 str_parms_destroy(reply);
2729 }
2730 if (query) {
2731 str_parms_destroy(query);
2732 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002733 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2734 return NULL;
2735 }
2736
Eric Laurent994a6932013-07-17 11:51:42 -07002737 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2739 if (ret >= 0) {
2740 value[0] = '\0';
2741 i = 0;
2742 while (out->supported_channel_masks[i] != 0) {
2743 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2744 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2745 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002746 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002748 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 first = false;
2750 break;
2751 }
2752 }
2753 i++;
2754 }
2755 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2756 str = str_parms_to_str(reply);
2757 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002758 voice_extn_out_get_parameters(out, query, reply);
2759 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002760 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002761 free(str);
2762 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002765
Alexy Joseph62142aa2015-11-16 15:10:34 -08002766
2767 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2768 if (ret >= 0) {
2769 value[0] = '\0';
2770 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2771 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302772 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002773 } else {
2774 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302775 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002776 }
2777 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002778 if (str)
2779 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002780 str = str_parms_to_str(reply);
2781 }
2782
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002783 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2784 if (ret >= 0) {
2785 value[0] = '\0';
2786 i = 0;
2787 first = true;
2788 while (out->supported_formats[i] != 0) {
2789 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2790 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2791 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002792 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002793 }
2794 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2795 first = false;
2796 break;
2797 }
2798 }
2799 i++;
2800 }
2801 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002802 if (str)
2803 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002804 str = str_parms_to_str(reply);
2805 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002806
2807 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2808 if (ret >= 0) {
2809 value[0] = '\0';
2810 i = 0;
2811 first = true;
2812 while (out->supported_sample_rates[i] != 0) {
2813 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2814 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2815 if (!first) {
2816 strlcat(value, "|", sizeof(value));
2817 }
2818 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2819 first = false;
2820 break;
2821 }
2822 }
2823 i++;
2824 }
2825 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2826 if (str)
2827 free(str);
2828 str = str_parms_to_str(reply);
2829 }
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 str_parms_destroy(query);
2832 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002833 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 return str;
2835}
2836
2837static uint32_t out_get_latency(const struct audio_stream_out *stream)
2838{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002839 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002841 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842
Alexy Josephaa54c872014-12-03 02:46:47 -08002843 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002844 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002845 } else if (out->realtime) {
2846 // since the buffer won't be filled up faster than realtime,
2847 // return a smaller number
2848 if (out->config.rate)
2849 period_ms = (out->af_period_multiplier * out->config.period_size *
2850 1000) / (out->config.rate);
2851 else
2852 period_ms = 0;
2853 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002854 } else {
2855 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002857 }
2858
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302859 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002860 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861}
2862
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302863static float AmpToDb(float amplification)
2864{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302865 float db = DSD_VOLUME_MIN_DB;
2866 if (amplification > 0) {
2867 db = 20 * log10(amplification);
2868 if(db < DSD_VOLUME_MIN_DB)
2869 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302870 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302871 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302872}
2873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874static int out_set_volume(struct audio_stream_out *stream, float left,
2875 float right)
2876{
Eric Laurenta9024de2013-04-04 09:19:12 -07002877 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 int volume[2];
2879
Eric Laurenta9024de2013-04-04 09:19:12 -07002880 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2881 /* only take left channel into account: the API is for stereo anyway */
2882 out->muted = (left == 0.0f);
2883 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002884 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302885 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002886 /*
2887 * Set mute or umute on HDMI passthrough stream.
2888 * Only take left channel into account.
2889 * Mute is 0 and unmute 1
2890 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302891 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302892 } else if (out->format == AUDIO_FORMAT_DSD){
2893 char mixer_ctl_name[128] = "DSD Volume";
2894 struct audio_device *adev = out->dev;
2895 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2896
2897 if (!ctl) {
2898 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2899 __func__, mixer_ctl_name);
2900 return -EINVAL;
2901 }
2902 volume[0] = (int)(AmpToDb(left));
2903 volume[1] = (int)(AmpToDb(right));
2904 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2905 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002906 } else {
2907 char mixer_ctl_name[128];
2908 struct audio_device *adev = out->dev;
2909 struct mixer_ctl *ctl;
2910 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002911 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2914 "Compress Playback %d Volume", pcm_device_id);
2915 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2916 if (!ctl) {
2917 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2918 __func__, mixer_ctl_name);
2919 return -EINVAL;
2920 }
2921 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2922 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2923 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2924 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002926 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 return -ENOSYS;
2929}
2930
2931static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2932 size_t bytes)
2933{
2934 struct stream_out *out = (struct stream_out *)stream;
2935 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302936 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002937 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002939 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302940
Naresh Tanniru80659832014-06-04 18:17:56 +05302941 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002942
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302943 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302944 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302945 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2946 pthread_mutex_unlock(&out->lock);
2947 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302948 } else {
2949 /* increase written size during SSR to avoid mismatch
2950 * with the written frames count in AF
2951 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002952 // bytes per frame
2953 size_t bpf = audio_bytes_per_sample(out->format) *
2954 audio_channel_count_from_out_mask(out->channel_mask);
2955 if (bpf != 0)
2956 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302957 ALOGD(" %s: sound card is not active/SSR state", __func__);
2958 ret= -EIO;
2959 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302960 }
2961 }
2962
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302963 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302964 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2965 if (audio_bytes_per_sample(out->format) != 0)
2966 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2967 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302968 goto exit;
2969 }
2970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002972 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002973 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002974 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2975 ret = voice_extn_compress_voip_start_output_stream(out);
2976 else
2977 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002978 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002981 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 goto exit;
2983 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002984
2985 if (last_known_cal_step != -1) {
2986 ALOGD("%s: retry previous failed cal level set", __func__);
2987 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2988 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990
Ashish Jain81eb2a82015-05-13 10:52:34 +05302991 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002992 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302993 adev->is_channel_status_set = true;
2994 }
2995
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002996 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002997 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002998 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002999 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003000 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3001 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303002 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3003 ALOGD("copl(%p):send next track params in gapless", out);
3004 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3005 out->send_next_track_params = false;
3006 out->is_compr_metadata_avail = false;
3007 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003008 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303009 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303010 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003011
Ashish Jain83a6cc22016-06-28 14:34:17 +05303012 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303013 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303014 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303015 pthread_mutex_unlock(&out->lock);
3016 return -EINVAL;
3017 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303018 audio_format_t dst_format = out->hal_op_format;
3019 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303020
3021 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3022 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3023
Ashish Jain83a6cc22016-06-28 14:34:17 +05303024 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303025 dst_format,
3026 buffer,
3027 src_format,
3028 frames);
3029
Ashish Jain83a6cc22016-06-28 14:34:17 +05303030 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303031 bytes_to_write);
3032
3033 /*Convert written bytes in audio flinger format*/
3034 if (ret > 0)
3035 ret = ((ret * format_to_bitwidth_table[out->format]) /
3036 format_to_bitwidth_table[dst_format]);
3037 }
3038 } else
3039 ret = compress_write(out->compr, buffer, bytes);
3040
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303041 if (ret < 0)
3042 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303043 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303044 /*msg to cb thread only if non blocking write is enabled*/
3045 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303046 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303048 } else if (-ENETRESET == ret) {
3049 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3050 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3051 pthread_mutex_unlock(&out->lock);
3052 out_standby(&out->stream.common);
3053 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 }
Ashish Jain5106d362016-05-11 19:23:33 +05303055 if ( ret == (ssize_t)bytes && !out->non_blocking)
3056 out->written += bytes;
3057
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303058 /* Call compr start only when non-zero bytes of data is there to be rendered */
3059 if (!out->playback_started && ret > 0) {
3060 int status = compress_start(out->compr);
3061 if (status < 0) {
3062 ret = status;
3063 ALOGE("%s: compr start failed with err %d", __func__, errno);
3064 goto exit;
3065 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003066 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 out->playback_started = 1;
3068 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003069
3070 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3071 popcount(out->channel_mask),
3072 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 }
3074 pthread_mutex_unlock(&out->lock);
3075 return ret;
3076 } else {
3077 if (out->pcm) {
3078 if (out->muted)
3079 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003080
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303081 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003082
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003083 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003084
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003085 if (out->config.rate)
3086 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3087 out->config.rate;
3088
3089 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3090
3091 request_out_focus(out, ns);
3092
3093 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003094 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003095 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303096 out->convert_buffer != NULL) {
3097
3098 memcpy_by_audio_format(out->convert_buffer,
3099 out->hal_op_format,
3100 buffer,
3101 out->hal_ip_format,
3102 out->config.period_size * out->config.channels);
3103
3104 ret = pcm_write(out->pcm, out->convert_buffer,
3105 (out->config.period_size *
3106 out->config.channels *
3107 format_to_bitwidth_table[out->hal_op_format]));
3108 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003109 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303110 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003111
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003112 release_out_focus(out);
3113
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303114 if (ret < 0)
3115 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303116 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3117 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3118 else
3119 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 }
3122
3123exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303124 /* ToDo: There may be a corner case when SSR happens back to back during
3125 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303126 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303127 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303128 }
3129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 pthread_mutex_unlock(&out->lock);
3131
3132 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003133 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003134 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303135 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303136 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303137 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303138 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303139 out->standby = true;
3140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303142 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3143 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3144 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 }
3146 return bytes;
3147}
3148
3149static int out_get_render_position(const struct audio_stream_out *stream,
3150 uint32_t *dsp_frames)
3151{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303153 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003154
3155 if (dsp_frames == NULL)
3156 return -EINVAL;
3157
3158 *dsp_frames = 0;
3159 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003160 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303161
3162 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3163 * this operation and adev_close_output_stream(where out gets reset).
3164 */
3165 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3166 *dsp_frames = get_actual_pcm_frames_rendered(out);
3167 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3168 return 0;
3169 }
3170
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003171 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303172 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303173 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303175 if (ret < 0)
3176 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003177 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303178 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003179 }
3180 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303181 if (-ENETRESET == ret) {
3182 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3183 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3184 return -EINVAL;
3185 } else if(ret < 0) {
3186 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3187 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303188 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3189 /*
3190 * Handle corner case where compress session is closed during SSR
3191 * and timestamp is queried
3192 */
3193 ALOGE(" ERROR: sound card not active, return error");
3194 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303195 } else {
3196 return 0;
3197 }
Zhou Song32a556e2015-05-05 10:46:56 +08003198 } else if (audio_is_linear_pcm(out->format)) {
3199 *dsp_frames = out->written;
3200 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201 } else
3202 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203}
3204
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003205static int out_add_audio_effect(const struct audio_stream *stream __unused,
3206 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207{
3208 return 0;
3209}
3210
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003211static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3212 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213{
3214 return 0;
3215}
3216
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003217static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3218 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219{
3220 return -EINVAL;
3221}
3222
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003223static int out_get_presentation_position(const struct audio_stream_out *stream,
3224 uint64_t *frames, struct timespec *timestamp)
3225{
3226 struct stream_out *out = (struct stream_out *)stream;
3227 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003228 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003229
Ashish Jain5106d362016-05-11 19:23:33 +05303230 /* below piece of code is not guarded against any lock because audioFliner serializes
3231 * this operation and adev_close_output_stream( where out gets reset).
3232 */
3233 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3234 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3235 *frames = get_actual_pcm_frames_rendered(out);
3236 /* this is the best we can do */
3237 clock_gettime(CLOCK_MONOTONIC, timestamp);
3238 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3239 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3240 return 0;
3241 }
3242
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003243 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003244
Ashish Jain5106d362016-05-11 19:23:33 +05303245 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3246 ret = compress_get_tstamp(out->compr, &dsp_frames,
3247 &out->sample_rate);
3248 ALOGVV("%s rendered frames %ld sample_rate %d",
3249 __func__, dsp_frames, out->sample_rate);
3250 *frames = dsp_frames;
3251 if (ret < 0)
3252 ret = -errno;
3253 if (-ENETRESET == ret) {
3254 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3255 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3256 ret = -EINVAL;
3257 } else
3258 ret = 0;
3259 /* this is the best we can do */
3260 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003261 } else {
3262 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003263 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003264 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3265 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003266 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003267 // This adjustment accounts for buffering after app processor.
3268 // It is based on estimated DSP latency per use case, rather than exact.
3269 signed_frames -=
3270 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3271
Eric Laurent949a0892013-09-20 09:20:13 -07003272 // It would be unusual for this value to be negative, but check just in case ...
3273 if (signed_frames >= 0) {
3274 *frames = signed_frames;
3275 ret = 0;
3276 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003277 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303278 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3279 *frames = out->written;
3280 clock_gettime(CLOCK_MONOTONIC, timestamp);
3281 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003282 }
3283 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003284 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003285 return ret;
3286}
3287
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288static int out_set_callback(struct audio_stream_out *stream,
3289 stream_callback_t callback, void *cookie)
3290{
3291 struct stream_out *out = (struct stream_out *)stream;
3292
3293 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003294 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 out->offload_callback = callback;
3296 out->offload_cookie = cookie;
3297 pthread_mutex_unlock(&out->lock);
3298 return 0;
3299}
3300
3301static int out_pause(struct audio_stream_out* stream)
3302{
3303 struct stream_out *out = (struct stream_out *)stream;
3304 int status = -ENOSYS;
3305 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003306 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003307 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003308 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303310 struct audio_device *adev = out->dev;
3311 int snd_scard_state = get_snd_card_state(adev);
3312
3313 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3314 status = compress_pause(out->compr);
3315
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003316 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003317
Mingming Yin21854652016-04-13 11:54:02 -07003318 if (audio_extn_passthru_is_active()) {
3319 ALOGV("offload use case, pause passthru");
3320 audio_extn_passthru_on_pause(out);
3321 }
3322
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303323 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003324 audio_extn_dts_notify_playback_state(out->usecase, 0,
3325 out->sample_rate, popcount(out->channel_mask),
3326 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 }
3328 pthread_mutex_unlock(&out->lock);
3329 }
3330 return status;
3331}
3332
3333static int out_resume(struct audio_stream_out* stream)
3334{
3335 struct stream_out *out = (struct stream_out *)stream;
3336 int status = -ENOSYS;
3337 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003338 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003339 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003341 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303343 struct audio_device *adev = out->dev;
3344 int snd_scard_state = get_snd_card_state(adev);
3345
Mingming Yin21854652016-04-13 11:54:02 -07003346 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3347 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3348 pthread_mutex_lock(&out->dev->lock);
3349 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003350 pthread_mutex_unlock(&out->dev->lock);
3351 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303352 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003353 }
3354 if (!status) {
3355 out->offload_state = OFFLOAD_STATE_PLAYING;
3356 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303357 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003358 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3359 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 }
3361 pthread_mutex_unlock(&out->lock);
3362 }
3363 return status;
3364}
3365
3366static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3367{
3368 struct stream_out *out = (struct stream_out *)stream;
3369 int status = -ENOSYS;
3370 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003371 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003372 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3374 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3375 else
3376 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3377 pthread_mutex_unlock(&out->lock);
3378 }
3379 return status;
3380}
3381
3382static int out_flush(struct audio_stream_out* stream)
3383{
3384 struct stream_out *out = (struct stream_out *)stream;
3385 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003386 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003387 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003388 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003389 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3390 stop_compressed_output_l(out);
3391 out->written = 0;
3392 } else {
3393 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3394 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003396 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397 return 0;
3398 }
3399 return -ENOSYS;
3400}
3401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402/** audio_stream_in implementation **/
3403static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3404{
3405 struct stream_in *in = (struct stream_in *)stream;
3406
3407 return in->config.rate;
3408}
3409
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003410static int in_set_sample_rate(struct audio_stream *stream __unused,
3411 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412{
3413 return -ENOSYS;
3414}
3415
3416static size_t in_get_buffer_size(const struct audio_stream *stream)
3417{
3418 struct stream_in *in = (struct stream_in *)stream;
3419
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003420 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3421 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003422 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3423 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303424 else if(audio_extn_cin_attached_usecase(in->usecase))
3425 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003426
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003427 return in->config.period_size * in->af_period_multiplier *
3428 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429}
3430
3431static uint32_t in_get_channels(const struct audio_stream *stream)
3432{
3433 struct stream_in *in = (struct stream_in *)stream;
3434
3435 return in->channel_mask;
3436}
3437
3438static audio_format_t in_get_format(const struct audio_stream *stream)
3439{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003440 struct stream_in *in = (struct stream_in *)stream;
3441
3442 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443}
3444
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003445static int in_set_format(struct audio_stream *stream __unused,
3446 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447{
3448 return -ENOSYS;
3449}
3450
3451static int in_standby(struct audio_stream *stream)
3452{
3453 struct stream_in *in = (struct stream_in *)stream;
3454 struct audio_device *adev = in->dev;
3455 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303456 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3457 stream, in->usecase, use_case_table[in->usecase]);
3458
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003459 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003460 if (!in->standby && in->is_st_session) {
3461 ALOGD("%s: sound trigger pcm stop lab", __func__);
3462 audio_extn_sound_trigger_stop_lab(in);
3463 in->standby = 1;
3464 }
3465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003467 if (adev->adm_deregister_stream)
3468 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3469
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003470 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003472 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3473 voice_extn_compress_voip_close_input_stream(stream);
3474 ALOGD("VOIP input entered standby");
3475 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303476 if (audio_extn_cin_attached_usecase(in->usecase))
3477 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003478 if (in->pcm) {
3479 pcm_close(in->pcm);
3480 in->pcm = NULL;
3481 }
3482 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003483 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003484 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 }
3486 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003487 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 return status;
3489}
3490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003491static int in_dump(const struct audio_stream *stream __unused,
3492 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493{
3494 return 0;
3495}
3496
3497static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3498{
3499 struct stream_in *in = (struct stream_in *)stream;
3500 struct audio_device *adev = in->dev;
3501 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003503 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303505 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 parms = str_parms_create_str(kvpairs);
3507
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303508 if (!parms)
3509 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003510 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003511 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003512
3513 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3514 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 val = atoi(value);
3516 /* no audio source uses val == 0 */
3517 if ((in->source != val) && (val != 0)) {
3518 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003519 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3520 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3521 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003522 (in->config.rate == 8000 || in->config.rate == 16000 ||
3523 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003524 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003525 err = voice_extn_compress_voip_open_input_stream(in);
3526 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003527 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003528 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003529 }
3530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 }
3532 }
3533
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003534 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3535 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003537 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 in->device = val;
3539 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003540 if (!in->standby && !in->is_st_session) {
3541 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003542 if (adev->adm_on_routing_change)
3543 adev->adm_on_routing_change(adev->adm_data,
3544 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003545 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 }
3548 }
3549
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303550 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3551 if (err >= 0) {
3552 strlcpy(in->profile, value, sizeof(in->profile));
3553 ALOGV("updating stream profile with value '%s'", in->profile);
3554 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3555 &adev->streams_input_cfg_list,
3556 in->device, in->flags, in->format,
3557 in->sample_rate, in->bit_width,
3558 in->profile, &in->app_type_cfg);
3559 }
3560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003562 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563
3564 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303565error:
Eric Laurent994a6932013-07-17 11:51:42 -07003566 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 return ret;
3568}
3569
3570static char* in_get_parameters(const struct audio_stream *stream,
3571 const char *keys)
3572{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003573 struct stream_in *in = (struct stream_in *)stream;
3574 struct str_parms *query = str_parms_create_str(keys);
3575 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003576 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003577
3578 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003579 if (reply) {
3580 str_parms_destroy(reply);
3581 }
3582 if (query) {
3583 str_parms_destroy(query);
3584 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003585 ALOGE("in_get_parameters: failed to create query or reply");
3586 return NULL;
3587 }
3588
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003589 ALOGV("%s: enter: keys - %s", __func__, keys);
3590
3591 voice_extn_in_get_parameters(in, query, reply);
3592
3593 str = str_parms_to_str(reply);
3594 str_parms_destroy(query);
3595 str_parms_destroy(reply);
3596
3597 ALOGV("%s: exit: returns - %s", __func__, str);
3598 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599}
3600
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003601static int in_set_gain(struct audio_stream_in *stream __unused,
3602 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603{
3604 return 0;
3605}
3606
3607static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3608 size_t bytes)
3609{
3610 struct stream_in *in = (struct stream_in *)stream;
3611 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303612 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303613 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303614 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003616 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303617
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003618 if (in->is_st_session) {
3619 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3620 /* Read from sound trigger HAL */
3621 audio_extn_sound_trigger_read(in, buffer, bytes);
3622 pthread_mutex_unlock(&in->lock);
3623 return bytes;
3624 }
3625
Ashish Jainbbce4322016-02-16 13:25:27 +05303626 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003627 ALOGD(" %s: sound card is not active/SSR state", __func__);
3628 ret= -EIO;;
3629 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303630 }
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003633 pthread_mutex_lock(&adev->lock);
3634 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3635 ret = voice_extn_compress_voip_start_input_stream(in);
3636 else
3637 ret = start_input_stream(in);
3638 pthread_mutex_unlock(&adev->lock);
3639 if (ret != 0) {
3640 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 }
3642 in->standby = 0;
3643 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003645 // what's the duration requested by the client?
3646 long ns = 0;
3647
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303648 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003649 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3650 in->config.rate;
3651
3652 request_in_focus(in, ns);
3653 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003654
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303655 if (audio_extn_cin_attached_usecase(in->usecase)) {
3656 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3657 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303658 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003659 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303660 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003661 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003662 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303664 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003665 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303666 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3667 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3668 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3669 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303670 ret = -EINVAL;
3671 goto exit;
3672 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303673 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303674 ret = -errno;
3675 }
3676 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303677 /* bytes read is always set to bytes for non compress usecases */
3678 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 }
3680
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003681 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 /*
3684 * Instead of writing zeroes here, we could trust the hardware
3685 * to always provide zeroes when muted.
3686 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303687 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3688 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 memset(buffer, 0, bytes);
3690
3691exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303692 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303693 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003694 if (-ENETRESET == ret)
3695 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 pthread_mutex_unlock(&in->lock);
3698
3699 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303700 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303701 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303702 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303703 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303704 in->standby = true;
3705 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303706 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003708 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303709 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303710 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303712 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713}
3714
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003715static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716{
3717 return 0;
3718}
3719
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003720static int add_remove_audio_effect(const struct audio_stream *stream,
3721 effect_handle_t effect,
3722 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003724 struct stream_in *in = (struct stream_in *)stream;
3725 int status = 0;
3726 effect_descriptor_t desc;
3727
3728 status = (*effect)->get_descriptor(effect, &desc);
3729 if (status != 0)
3730 return status;
3731
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003732 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003733 pthread_mutex_lock(&in->dev->lock);
3734 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3735 in->enable_aec != enable &&
3736 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3737 in->enable_aec = enable;
3738 if (!in->standby)
3739 select_devices(in->dev, in->usecase);
3740 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003741 if (in->enable_ns != enable &&
3742 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3743 in->enable_ns = enable;
3744 if (!in->standby)
3745 select_devices(in->dev, in->usecase);
3746 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003747 pthread_mutex_unlock(&in->dev->lock);
3748 pthread_mutex_unlock(&in->lock);
3749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 return 0;
3751}
3752
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003753static int in_add_audio_effect(const struct audio_stream *stream,
3754 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755{
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, true);
3758}
3759
3760static int in_remove_audio_effect(const struct audio_stream *stream,
3761 effect_handle_t effect)
3762{
Eric Laurent994a6932013-07-17 11:51:42 -07003763 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003764 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765}
3766
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303767int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 audio_io_handle_t handle,
3769 audio_devices_t devices,
3770 audio_output_flags_t flags,
3771 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003772 struct audio_stream_out **stream_out,
3773 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774{
3775 struct audio_device *adev = (struct audio_device *)dev;
3776 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303777 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003778 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303781
3782 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3783 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003784 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303785 return -EINVAL;
3786 }
3787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3789
Mingming Yin3a941d42016-02-17 18:08:05 -08003790 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3791 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303792 devices, flags, &out->stream);
3793
3794
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003795 if (!out) {
3796 return -ENOMEM;
3797 }
3798
Haynes Mathew George204045b2015-02-25 20:32:03 -08003799 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003800 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003801 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 if (devices == AUDIO_DEVICE_NONE)
3804 devices = AUDIO_DEVICE_OUT_SPEAKER;
3805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 out->flags = flags;
3807 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003808 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003809 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003810 out->sample_rate = config->sample_rate;
3811 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3812 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003813 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003814 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003815 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303816 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Mingming Yin3a941d42016-02-17 18:08:05 -08003818 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3819 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3820 pthread_mutex_lock(&adev->lock);
3821 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3822 ret = read_hdmi_sink_caps(out);
3823 pthread_mutex_unlock(&adev->lock);
3824 if (ret != 0) {
3825 if (ret == -ENOSYS) {
3826 /* ignore and go with default */
3827 ret = 0;
3828 } else {
3829 ALOGE("error reading hdmi sink caps");
3830 goto error_open;
3831 }
3832 }
3833 }
3834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003836 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303837 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3838 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003839 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3840 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3841
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003842 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003843 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3844 /*
3845 * Do not handle stereo output in Multi-channel cases
3846 * Stereo case is handled in normal playback path
3847 */
3848 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3849 ret = AUDIO_CHANNEL_OUT_STEREO;
3850 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003851
3852 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3853 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003854 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003855 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003856 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003857
3858 if (config->sample_rate == 0)
3859 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3860 if (config->channel_mask == 0)
3861 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003862 if (config->format == 0)
3863 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003864
3865 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003866 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003867 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3869 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003871 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003873 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003874 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003875 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003876 ret = voice_extn_compress_voip_open_output_stream(out);
3877 if (ret != 0) {
3878 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3879 __func__, ret);
3880 goto error_open;
3881 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003882 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3883 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3884
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003885 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3886 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3887 ALOGE("%s: Unsupported Offload information", __func__);
3888 ret = -EINVAL;
3889 goto error_open;
3890 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003891
Mingming Yin3a941d42016-02-17 18:08:05 -08003892 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003893 if(config->offload_info.format == 0)
3894 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003895 if (config->offload_info.sample_rate == 0)
3896 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003897 }
3898
Mingming Yin90310102013-11-13 16:57:00 -08003899 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303900 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003901 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 ret = -EINVAL;
3903 goto error_open;
3904 }
3905
3906 out->compr_config.codec = (struct snd_codec *)
3907 calloc(1, sizeof(struct snd_codec));
3908
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003909 if (!out->compr_config.codec) {
3910 ret = -ENOMEM;
3911 goto error_open;
3912 }
3913
vivek mehta0ea887a2015-08-26 14:01:20 -07003914 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303915 out->stream.pause = out_pause;
3916 out->stream.flush = out_flush;
3917 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003918 out->usecase = get_offload_usecase(adev, true);
3919 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003920 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003921 out->stream.set_callback = out_set_callback;
3922 out->stream.pause = out_pause;
3923 out->stream.resume = out_resume;
3924 out->stream.drain = out_drain;
3925 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003926 out->usecase = get_offload_usecase(adev, false);
3927 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003928 }
vivek mehta446c3962015-09-14 10:57:35 -07003929
3930 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003931 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3932 config->format == 0 && config->sample_rate == 0 &&
3933 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003934 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003935 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3936 } else {
3937 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3938 ret = -EEXIST;
3939 goto error_open;
3940 }
vivek mehta446c3962015-09-14 10:57:35 -07003941 }
3942
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003943 if (config->offload_info.channel_mask)
3944 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003945 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003946 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003947 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003948 } else {
3949 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3950 ret = -EINVAL;
3951 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003952 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003953
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003954 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003955 out->sample_rate = config->offload_info.sample_rate;
3956
Mingming Yin3ee55c62014-08-04 14:23:35 -07003957 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003958
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303959 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3960 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3961 audio_extn_dolby_send_ddp_endp_params(adev);
3962 audio_extn_dolby_set_dmid(adev);
3963 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003964
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003966 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003967 out->compr_config.codec->bit_rate =
3968 config->offload_info.bit_rate;
3969 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303970 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003971 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303972 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003973 /*TODO: Do we need to change it for passthrough */
3974 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975
Manish Dewangana6fc5442015-08-24 20:30:31 +05303976 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3977 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3978 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3979 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303980
3981 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3982 AUDIO_FORMAT_PCM) {
3983
3984 /*Based on platform support, configure appropriate alsa format for corresponding
3985 *hal input format.
3986 */
3987 out->compr_config.codec->format = hal_format_to_alsa(
3988 config->offload_info.format);
3989
Ashish Jain83a6cc22016-06-28 14:34:17 +05303990 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303991 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303992 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303993
3994 /*for direct PCM playback populate bit_width based on selected alsa format as
3995 *hal input format and alsa format might differ based on platform support.
3996 */
3997 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303998 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303999
4000 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4001
4002 /* Check if alsa session is configured with the same format as HAL input format,
4003 * if not then derive correct fragment size needed to accomodate the
4004 * conversion of HAL input format to alsa format.
4005 */
4006 audio_extn_utils_update_direct_pcm_fragment_size(out);
4007
4008 /*if hal input and output fragment size is different this indicates HAL input format is
4009 *not same as the alsa format
4010 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304011 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304012 /*Allocate a buffer to convert input data to the alsa configured format.
4013 *size of convert buffer is equal to the size required to hold one fragment size
4014 *worth of pcm data, this is because flinger does not write more than fragment_size
4015 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304016 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4017 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304018 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4019 ret = -ENOMEM;
4020 goto error_open;
4021 }
4022 }
4023 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4024 out->compr_config.fragment_size =
4025 audio_extn_passthru_get_buffer_size(&config->offload_info);
4026 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4027 } else {
4028 out->compr_config.fragment_size =
4029 platform_get_compress_offload_buffer_size(&config->offload_info);
4030 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4031 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004032
Amit Shekhar6f461b12014-08-01 14:52:58 -07004033 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304034 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004035
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4037 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004038
Alexy Josephaa54c872014-12-03 02:46:47 -08004039
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004040 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304041 out->send_next_track_params = false;
4042 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004043 out->offload_state = OFFLOAD_STATE_IDLE;
4044 out->playback_started = 0;
4045
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004046 audio_extn_dts_create_state_notifier_node(out->usecase);
4047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4049 __func__, config->offload_info.version,
4050 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304051
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304052 /* Check if DSD audio format is supported in codec
4053 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304054 */
4055
4056 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304057 (!platform_check_codec_dsd_support(adev->platform) ||
4058 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304059 ret = -EINVAL;
4060 goto error_open;
4061 }
4062
Ashish Jain5106d362016-05-11 19:23:33 +05304063 /* Disable gapless if any of the following is true
4064 * passthrough playback
4065 * AV playback
4066 * Direct PCM playback
4067 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304068 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304069 (config->format == AUDIO_FORMAT_DSD) ||
4070 config->offload_info.has_video ||
4071 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304072 check_and_set_gapless_mode(adev, false);
4073 } else
4074 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004075
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304076 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004077 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4078 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304079 if (config->format == AUDIO_FORMAT_DSD) {
4080 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4081 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4082 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004083
4084 create_offload_callback_thread(out);
4085
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004086 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304087 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004088 if (ret != 0) {
4089 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4090 __func__, ret);
4091 goto error_open;
4092 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004093 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4094 if (config->sample_rate == 0)
4095 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4096 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4097 config->sample_rate != 8000) {
4098 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4099 ret = -EINVAL;
4100 goto error_open;
4101 }
4102 out->sample_rate = config->sample_rate;
4103 out->config.rate = config->sample_rate;
4104 if (config->format == AUDIO_FORMAT_DEFAULT)
4105 config->format = AUDIO_FORMAT_PCM_16_BIT;
4106 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4107 config->format = AUDIO_FORMAT_PCM_16_BIT;
4108 ret = -EINVAL;
4109 goto error_open;
4110 }
4111 out->format = config->format;
4112 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4113 out->config = pcm_config_afe_proxy_playback;
4114 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004115 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304116 unsigned int channels = 0;
4117 /*Update config params to default if not set by the caller*/
4118 if (config->sample_rate == 0)
4119 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4120 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4121 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4122 if (config->format == AUDIO_FORMAT_DEFAULT)
4123 config->format = AUDIO_FORMAT_PCM_16_BIT;
4124
4125 channels = audio_channel_count_from_out_mask(out->channel_mask);
4126
Ashish Jain83a6cc22016-06-28 14:34:17 +05304127 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4128 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004129 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4130 out->flags);
4131 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304132 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4133 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4134 out->config = pcm_config_low_latency;
4135 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4136 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4137 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304138 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4139 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4140 if (out->config.period_size <= 0) {
4141 ALOGE("Invalid configuration period size is not valid");
4142 ret = -EINVAL;
4143 goto error_open;
4144 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304145 } else {
4146 /* primary path is the default path selected if no other outputs are available/suitable */
4147 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4148 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4149 }
4150 out->hal_ip_format = format = out->format;
4151 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4152 out->hal_op_format = pcm_format_to_hal(out->config.format);
4153 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4154 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004155 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304156 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304157 if (out->hal_ip_format != out->hal_op_format) {
4158 uint32_t buffer_size = out->config.period_size *
4159 format_to_bitwidth_table[out->hal_op_format] *
4160 out->config.channels;
4161 out->convert_buffer = calloc(1, buffer_size);
4162 if (out->convert_buffer == NULL){
4163 ALOGE("Allocation failed for convert buffer for size %d",
4164 out->compr_config.fragment_size);
4165 ret = -ENOMEM;
4166 goto error_open;
4167 }
4168 ALOGD("Convert buffer allocated of size %d", buffer_size);
4169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 }
4171
Ashish Jain83a6cc22016-06-28 14:34:17 +05304172 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4173 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4174
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004175 /* TODO remove this hardcoding and check why width is zero*/
4176 if (out->bit_width == 0)
4177 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304178 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004179 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004180 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304181 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304182 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004183 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4184 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4185 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004186 if(adev->primary_output == NULL)
4187 adev->primary_output = out;
4188 else {
4189 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004190 ret = -EEXIST;
4191 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004192 }
4193 }
4194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 /* Check if this usecase is already existing */
4196 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004197 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4198 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004201 ret = -EEXIST;
4202 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203 }
4204 pthread_mutex_unlock(&adev->lock);
4205
4206 out->stream.common.get_sample_rate = out_get_sample_rate;
4207 out->stream.common.set_sample_rate = out_set_sample_rate;
4208 out->stream.common.get_buffer_size = out_get_buffer_size;
4209 out->stream.common.get_channels = out_get_channels;
4210 out->stream.common.get_format = out_get_format;
4211 out->stream.common.set_format = out_set_format;
4212 out->stream.common.standby = out_standby;
4213 out->stream.common.dump = out_dump;
4214 out->stream.common.set_parameters = out_set_parameters;
4215 out->stream.common.get_parameters = out_get_parameters;
4216 out->stream.common.add_audio_effect = out_add_audio_effect;
4217 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4218 out->stream.get_latency = out_get_latency;
4219 out->stream.set_volume = out_set_volume;
4220 out->stream.write = out_write;
4221 out->stream.get_render_position = out_get_render_position;
4222 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004223 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004225 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004227 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004228 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229
4230 config->format = out->stream.common.get_format(&out->stream.common);
4231 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4232 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4233
4234 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304235 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004236 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004237
4238 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4239 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4240 popcount(out->channel_mask), out->playback_started);
4241
Eric Laurent994a6932013-07-17 11:51:42 -07004242 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004244
4245error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304246 if (out->convert_buffer)
4247 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004248 free(out);
4249 *stream_out = NULL;
4250 ALOGD("%s: exit: ret %d", __func__, ret);
4251 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252}
4253
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304254void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 struct audio_stream_out *stream)
4256{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004257 struct stream_out *out = (struct stream_out *)stream;
4258 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004259 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004260
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304261 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4262
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004263 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304264 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004265 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304266 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004267 if(ret != 0)
4268 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4269 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004270 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004271 out_standby(&stream->common);
4272
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004273 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004274 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004275 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004276 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004277 if (out->compr_config.codec != NULL)
4278 free(out->compr_config.codec);
4279 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004280
Ashish Jain83a6cc22016-06-28 14:34:17 +05304281 if (out->convert_buffer != NULL) {
4282 free(out->convert_buffer);
4283 out->convert_buffer = NULL;
4284 }
4285
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004286 if (adev->voice_tx_output == out)
4287 adev->voice_tx_output = NULL;
4288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004289 pthread_cond_destroy(&out->cond);
4290 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004292 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293}
4294
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004295static void close_compress_sessions(struct audio_device *adev)
4296{
Mingming Yin7b762e72015-03-04 13:47:32 -08004297 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304298 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004299 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004300 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304301
4302 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004303 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304304 if (is_offload_usecase(usecase->id)) {
4305 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004306 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4307 out = usecase->stream.out;
4308 pthread_mutex_unlock(&adev->lock);
4309 out_standby(&out->stream.common);
4310 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004311 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004312 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304313 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004314 }
4315 pthread_mutex_unlock(&adev->lock);
4316}
4317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4319{
4320 struct audio_device *adev = (struct audio_device *)dev;
4321 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004323 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004324 int ret;
4325 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004327 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304330 if (!parms)
4331 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004332 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4333 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304334 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304335 if (strstr(snd_card_status, "OFFLINE")) {
4336 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304337 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004338 //close compress sessions on OFFLINE status
4339 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304340 } else if (strstr(snd_card_status, "ONLINE")) {
4341 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304342 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004343 //send dts hpx license if enabled
4344 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304345 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304346 }
4347
4348 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004349 status = voice_set_parameters(adev, parms);
4350 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004351 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004353 status = platform_set_parameters(adev->platform, parms);
4354 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004355 goto done;
4356
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004357 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4358 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004359 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4361 adev->bluetooth_nrec = true;
4362 else
4363 adev->bluetooth_nrec = false;
4364 }
4365
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004366 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4367 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4369 adev->screen_off = false;
4370 else
4371 adev->screen_off = true;
4372 }
4373
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004374 ret = str_parms_get_int(parms, "rotation", &val);
4375 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004376 bool reverse_speakers = false;
4377 switch(val) {
4378 // FIXME: note that the code below assumes that the speakers are in the correct placement
4379 // relative to the user when the device is rotated 90deg from its default rotation. This
4380 // assumption is device-specific, not platform-specific like this code.
4381 case 270:
4382 reverse_speakers = true;
4383 break;
4384 case 0:
4385 case 90:
4386 case 180:
4387 break;
4388 default:
4389 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004390 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004391 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004392 if (status == 0) {
4393 if (adev->speaker_lr_swap != reverse_speakers) {
4394 adev->speaker_lr_swap = reverse_speakers;
4395 // only update the selected device if there is active pcm playback
4396 struct audio_usecase *usecase;
4397 struct listnode *node;
4398 list_for_each(node, &adev->usecase_list) {
4399 usecase = node_to_item(node, struct audio_usecase, list);
4400 if (usecase->type == PCM_PLAYBACK) {
4401 select_devices(adev, usecase->id);
4402 break;
4403 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004404 }
4405 }
4406 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004407 }
4408
Mingming Yin514a8bc2014-07-29 15:22:21 -07004409 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4410 if (ret >= 0) {
4411 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4412 adev->bt_wb_speech_enabled = true;
4413 else
4414 adev->bt_wb_speech_enabled = false;
4415 }
4416
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004417 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4418 if (ret >= 0) {
4419 val = atoi(value);
4420 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004421 ALOGV("cache new ext disp type and edid");
4422 ret = platform_get_ext_disp_type(adev->platform);
4423 if (ret < 0) {
4424 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004425 status = ret;
4426 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004427 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004428 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004429 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004430 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004431 /*
4432 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4433 * Per AudioPolicyManager, USB device is higher priority than WFD.
4434 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4435 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4436 * starting voice call on USB
4437 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004438 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4439 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004440 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4441 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004442 }
vivek mehta344576a2016-04-12 18:56:03 -07004443 ALOGV("detected USB connect .. disable proxy");
4444 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004445 }
4446 }
4447
4448 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4449 if (ret >= 0) {
4450 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004451 /*
4452 * The HDMI / Displayport disconnect handling has been moved to
4453 * audio extension to ensure that its parameters are not
4454 * invalidated prior to updating sysfs of the disconnect event
4455 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4456 */
4457 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004458 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004459 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4460 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304461 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4462 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004463 }
vivek mehta344576a2016-04-12 18:56:03 -07004464 ALOGV("detected USB disconnect .. enable proxy");
4465 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004466 }
4467 }
4468
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304469 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4470 if (ret >= 0) {
4471 struct audio_usecase *usecase;
4472 struct listnode *node;
4473 list_for_each(node, &adev->usecase_list) {
4474 usecase = node_to_item(node, struct audio_usecase, list);
4475 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004476 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304477 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304478 lock_output_stream(usecase->stream.out);
4479 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304480 //force device switch to re configure encoder
4481 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304482 audio_extn_a2dp_set_handoff_mode(false);
4483 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304484 break;
4485 }
4486 }
4487 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304488 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004489done:
4490 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004491 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304492error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004493 ALOGV("%s: exit with code(%d)", __func__, status);
4494 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495}
4496
4497static char* adev_get_parameters(const struct audio_hw_device *dev,
4498 const char *keys)
4499{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004500 struct audio_device *adev = (struct audio_device *)dev;
4501 struct str_parms *reply = str_parms_create();
4502 struct str_parms *query = str_parms_create_str(keys);
4503 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304504 char value[256] = {0};
4505 int ret = 0;
4506
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004507 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004508 if (reply) {
4509 str_parms_destroy(reply);
4510 }
4511 if (query) {
4512 str_parms_destroy(query);
4513 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004514 ALOGE("adev_get_parameters: failed to create query or reply");
4515 return NULL;
4516 }
4517
Naresh Tannirud7205b62014-06-20 02:54:48 +05304518 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4519 sizeof(value));
4520 if (ret >=0) {
4521 int val = 1;
4522 pthread_mutex_lock(&adev->snd_card_status.lock);
4523 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4524 val = 0;
4525 pthread_mutex_unlock(&adev->snd_card_status.lock);
4526 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4527 goto exit;
4528 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004529
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004530 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004531 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004532 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004533 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304534 pthread_mutex_unlock(&adev->lock);
4535
Naresh Tannirud7205b62014-06-20 02:54:48 +05304536exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004537 str = str_parms_to_str(reply);
4538 str_parms_destroy(query);
4539 str_parms_destroy(reply);
4540
4541 ALOGV("%s: exit: returns - %s", __func__, str);
4542 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543}
4544
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004545static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546{
4547 return 0;
4548}
4549
4550static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4551{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004552 int ret;
4553 struct audio_device *adev = (struct audio_device *)dev;
4554 pthread_mutex_lock(&adev->lock);
4555 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004556 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004557 pthread_mutex_unlock(&adev->lock);
4558 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559}
4560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004561static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4562 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563{
4564 return -ENOSYS;
4565}
4566
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004567static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4568 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569{
4570 return -ENOSYS;
4571}
4572
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004573static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4574 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575{
4576 return -ENOSYS;
4577}
4578
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004579static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4580 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581{
4582 return -ENOSYS;
4583}
4584
4585static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4586{
4587 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 pthread_mutex_lock(&adev->lock);
4590 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004591 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004593 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004594 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004595 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004596 adev->current_call_output = NULL;
4597 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 }
4599 pthread_mutex_unlock(&adev->lock);
4600 return 0;
4601}
4602
4603static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4604{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004605 int ret;
4606
4607 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004608 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004609 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4610 pthread_mutex_unlock(&adev->lock);
4611
4612 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613}
4614
4615static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4616{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004617 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618 return 0;
4619}
4620
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004621static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 const struct audio_config *config)
4623{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004624 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004626 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4627 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628}
4629
4630static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004631 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 audio_devices_t devices,
4633 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004634 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304635 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004636 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004637 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638{
4639 struct audio_device *adev = (struct audio_device *)dev;
4640 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004641 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004642 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004643 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304644 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304647 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4648 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304650 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651
4652 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004653
4654 if (!in) {
4655 ALOGE("failed to allocate input stream");
4656 return -ENOMEM;
4657 }
4658
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304659 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304660 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4661 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004662 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004663 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665 in->stream.common.get_sample_rate = in_get_sample_rate;
4666 in->stream.common.set_sample_rate = in_set_sample_rate;
4667 in->stream.common.get_buffer_size = in_get_buffer_size;
4668 in->stream.common.get_channels = in_get_channels;
4669 in->stream.common.get_format = in_get_format;
4670 in->stream.common.set_format = in_set_format;
4671 in->stream.common.standby = in_standby;
4672 in->stream.common.dump = in_dump;
4673 in->stream.common.set_parameters = in_set_parameters;
4674 in->stream.common.get_parameters = in_get_parameters;
4675 in->stream.common.add_audio_effect = in_add_audio_effect;
4676 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4677 in->stream.set_gain = in_set_gain;
4678 in->stream.read = in_read;
4679 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4680
4681 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004682 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684 in->standby = 1;
4685 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004686 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004687 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004689 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004690 if (in->realtime) {
4691 in->config = pcm_config_audio_capture_rt;
4692 in->sample_rate = in->config.rate;
4693 in->af_period_multiplier = af_period_multiplier;
4694 } else {
4695 in->config = pcm_config_audio_capture;
4696 in->config.rate = config->sample_rate;
4697 in->sample_rate = config->sample_rate;
4698 in->af_period_multiplier = 1;
4699 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304700 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304702 /* restrict 24 bit capture for unprocessed source only
4703 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4704 */
4705 if (config->format == AUDIO_FORMAT_DEFAULT) {
4706 config->format = AUDIO_FORMAT_PCM_16_BIT;
4707 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4708 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4709 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4710 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4711 bool ret_error = false;
4712 in->bit_width = 24;
4713 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4714 from HAL is 24_packed and 8_24
4715 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4716 24_packed return error indicating supported format is 24_packed
4717 *> In case of any other source requesting 24 bit or float return error
4718 indicating format supported is 16 bit only.
4719
4720 on error flinger will retry with supported format passed
4721 */
4722 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4723 (source != AUDIO_SOURCE_CAMCORDER)) {
4724 config->format = AUDIO_FORMAT_PCM_16_BIT;
4725 if (config->sample_rate > 48000)
4726 config->sample_rate = 48000;
4727 ret_error = true;
4728 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4729 in->config.format = PCM_FORMAT_S24_3LE;
4730 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4731 in->config.format = PCM_FORMAT_S24_LE;
4732 } else {
4733 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4734 ret_error = true;
4735 }
4736
4737 if (ret_error) {
4738 ret = -EINVAL;
4739 goto err_open;
4740 }
4741 }
4742
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304743 in->usecase = USECASE_AUDIO_RECORD;
4744 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4745 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4746 is_low_latency = true;
4747#if LOW_LATENCY_CAPTURE_USE_CASE
4748 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4749#endif
4750 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4751 }
4752
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304753 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304754 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4755 (adev->mode != AUDIO_MODE_IN_CALL)) {
4756 ret = -EINVAL;
4757 goto err_open;
4758 }
4759
4760 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4761 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004762 if (config->sample_rate == 0)
4763 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4764 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4765 config->sample_rate != 8000) {
4766 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4767 ret = -EINVAL;
4768 goto err_open;
4769 }
4770 if (config->format == AUDIO_FORMAT_DEFAULT)
4771 config->format = AUDIO_FORMAT_PCM_16_BIT;
4772 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4773 config->format = AUDIO_FORMAT_PCM_16_BIT;
4774 ret = -EINVAL;
4775 goto err_open;
4776 }
4777
4778 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4779 in->config = pcm_config_afe_proxy_record;
4780 in->config.channels = channel_count;
4781 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304782 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304783 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4784 in, config, &channel_mask_updated)) {
4785 if (channel_mask_updated == true) {
4786 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4787 __func__, config->channel_mask);
4788 ret = -EINVAL;
4789 goto err_open;
4790 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304791 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004792 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004793 audio_extn_compr_cap_format_supported(config->format) &&
4794 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004795 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304796 } else if (audio_extn_cin_applicable_stream(in)) {
4797 ret = audio_extn_cin_configure_input_stream(in);
4798 if (ret)
4799 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004800 } else {
4801 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004802 if (!in->realtime) {
4803 in->format = config->format;
4804 frame_size = audio_stream_in_frame_size(&in->stream);
4805 buffer_size = get_input_buffer_size(config->sample_rate,
4806 config->format,
4807 channel_count,
4808 is_low_latency);
4809 in->config.period_size = buffer_size / frame_size;
4810 }
4811
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004812 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004813 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004814 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004815 (in->config.rate == 8000 || in->config.rate == 16000 ||
4816 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004817 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4818 voice_extn_compress_voip_open_input_stream(in);
4819 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004820 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304822 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4823 &adev->streams_input_cfg_list,
4824 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304825 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304826
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004827 /* This stream could be for sound trigger lab,
4828 get sound trigger pcm if present */
4829 audio_extn_sound_trigger_check_and_get_session(in);
4830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004832 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004833 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
4835err_open:
4836 free(in);
4837 *stream_in = NULL;
4838 return ret;
4839}
4840
4841static void adev_close_input_stream(struct audio_hw_device *dev,
4842 struct audio_stream_in *stream)
4843{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004844 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004845 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004846 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304847
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304848 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004849
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304850 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004851 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304852
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004853 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304854 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004855 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304856 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004857 if (ret != 0)
4858 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4859 __func__, ret);
4860 } else
4861 in_standby(&stream->common);
4862
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004863 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004864 audio_extn_ssr_deinit();
4865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304867 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004868 audio_extn_compr_cap_format_supported(in->config.format))
4869 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304870
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304871 if (audio_extn_cin_attached_usecase(in->usecase))
4872 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004873
Mingming Yinfd7607b2016-01-22 12:48:44 -08004874 if (in->is_st_session) {
4875 ALOGV("%s: sound trigger pcm stop lab", __func__);
4876 audio_extn_sound_trigger_stop_lab(in);
4877 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004878 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879 return;
4880}
4881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004882static int adev_dump(const audio_hw_device_t *device __unused,
4883 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884{
4885 return 0;
4886}
4887
4888static int adev_close(hw_device_t *device)
4889{
4890 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004891
4892 if (!adev)
4893 return 0;
4894
4895 pthread_mutex_lock(&adev_init_lock);
4896
4897 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004898 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004899 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304900 audio_extn_utils_release_streams_cfg_lists(
4901 &adev->streams_output_cfg_list,
4902 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304903 if (audio_extn_qaf_is_enabled())
4904 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004905 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004906 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004907 free(adev->snd_dev_ref_cnt);
4908 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004909 if (adev->adm_deinit)
4910 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304911 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004912 free(device);
4913 adev = NULL;
4914 }
4915 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917 return 0;
4918}
4919
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004920/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4921 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4922 * just that it _might_ work.
4923 */
4924static int period_size_is_plausible_for_low_latency(int period_size)
4925{
4926 switch (period_size) {
4927 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004928 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004929 case 240:
4930 case 320:
4931 case 480:
4932 return 1;
4933 default:
4934 return 0;
4935 }
4936}
4937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938static int adev_open(const hw_module_t *module, const char *name,
4939 hw_device_t **device)
4940{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304941 int ret;
4942
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004943 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004944 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4945
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004946 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004947 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004948 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004949 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004950 ALOGD("%s: returning existing instance of adev", __func__);
4951 ALOGD("%s: exit", __func__);
4952 pthread_mutex_unlock(&adev_init_lock);
4953 return 0;
4954 }
4955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 adev = calloc(1, sizeof(struct audio_device));
4957
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004958 if (!adev) {
4959 pthread_mutex_unlock(&adev_init_lock);
4960 return -ENOMEM;
4961 }
4962
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004963 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004965 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4966 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4967 adev->device.common.module = (struct hw_module_t *)module;
4968 adev->device.common.close = adev_close;
4969
4970 adev->device.init_check = adev_init_check;
4971 adev->device.set_voice_volume = adev_set_voice_volume;
4972 adev->device.set_master_volume = adev_set_master_volume;
4973 adev->device.get_master_volume = adev_get_master_volume;
4974 adev->device.set_master_mute = adev_set_master_mute;
4975 adev->device.get_master_mute = adev_get_master_mute;
4976 adev->device.set_mode = adev_set_mode;
4977 adev->device.set_mic_mute = adev_set_mic_mute;
4978 adev->device.get_mic_mute = adev_get_mic_mute;
4979 adev->device.set_parameters = adev_set_parameters;
4980 adev->device.get_parameters = adev_get_parameters;
4981 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4982 adev->device.open_output_stream = adev_open_output_stream;
4983 adev->device.close_output_stream = adev_close_output_stream;
4984 adev->device.open_input_stream = adev_open_input_stream;
4985 adev->device.close_input_stream = adev_close_input_stream;
4986 adev->device.dump = adev_dump;
4987
4988 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004990 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004991 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004994 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004995 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004996 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004997 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004998 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004999 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005000 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005001 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305002 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305003 adev->perf_lock_opts[0] = 0x101;
5004 adev->perf_lock_opts[1] = 0x20E;
5005 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305006
5007 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5008 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005010 adev->platform = platform_init(adev);
5011 if (!adev->platform) {
5012 free(adev->snd_dev_ref_cnt);
5013 free(adev);
5014 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5015 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005016 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305017 pthread_mutex_destroy(&adev->lock);
5018 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005019 return -EINVAL;
5020 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005021
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305022 if (audio_extn_qaf_is_enabled()) {
5023 ret = audio_extn_qaf_init(adev);
5024 if (ret < 0) {
5025 free(adev);
5026 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5027 *device = NULL;
5028 pthread_mutex_unlock(&adev_init_lock);
5029 pthread_mutex_destroy(&adev->lock);
5030 return ret;
5031 }
5032
5033 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5034 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5035 }
5036
Naresh Tanniru4c630392014-05-12 01:05:52 +05305037 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5038
Eric Laurentc4aef752013-09-12 17:45:53 -07005039 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5040 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5041 if (adev->visualizer_lib == NULL) {
5042 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5043 } else {
5044 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5045 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005046 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005047 "visualizer_hal_start_output");
5048 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005049 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005050 "visualizer_hal_stop_output");
5051 }
5052 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305053 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005054 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005055 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005056 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005057
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005058 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5059 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5060 if (adev->offload_effects_lib == NULL) {
5061 ALOGE("%s: DLOPEN failed for %s", __func__,
5062 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5063 } else {
5064 ALOGV("%s: DLOPEN successful for %s", __func__,
5065 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5066 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305067 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005068 "offload_effects_bundle_hal_start_output");
5069 adev->offload_effects_stop_output =
5070 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5071 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005072 adev->offload_effects_set_hpx_state =
5073 (int (*)(bool))dlsym(adev->offload_effects_lib,
5074 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305075 adev->offload_effects_get_parameters =
5076 (void (*)(struct str_parms *, struct str_parms *))
5077 dlsym(adev->offload_effects_lib,
5078 "offload_effects_bundle_get_parameters");
5079 adev->offload_effects_set_parameters =
5080 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5081 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005082 }
5083 }
5084
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005085 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5086 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5087 if (adev->adm_lib == NULL) {
5088 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5089 } else {
5090 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5091 adev->adm_init = (adm_init_t)
5092 dlsym(adev->adm_lib, "adm_init");
5093 adev->adm_deinit = (adm_deinit_t)
5094 dlsym(adev->adm_lib, "adm_deinit");
5095 adev->adm_register_input_stream = (adm_register_input_stream_t)
5096 dlsym(adev->adm_lib, "adm_register_input_stream");
5097 adev->adm_register_output_stream = (adm_register_output_stream_t)
5098 dlsym(adev->adm_lib, "adm_register_output_stream");
5099 adev->adm_deregister_stream = (adm_deregister_stream_t)
5100 dlsym(adev->adm_lib, "adm_deregister_stream");
5101 adev->adm_request_focus = (adm_request_focus_t)
5102 dlsym(adev->adm_lib, "adm_request_focus");
5103 adev->adm_abandon_focus = (adm_abandon_focus_t)
5104 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005105 adev->adm_set_config = (adm_set_config_t)
5106 dlsym(adev->adm_lib, "adm_set_config");
5107 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5108 dlsym(adev->adm_lib, "adm_request_focus_v2");
5109 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5110 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5111 adev->adm_on_routing_change = (adm_on_routing_change_t)
5112 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005113 }
5114 }
5115
Mingming Yin514a8bc2014-07-29 15:22:21 -07005116 adev->bt_wb_speech_enabled = false;
5117
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005118 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005119 *device = &adev->device.common;
5120
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305121 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5122 &adev->streams_output_cfg_list,
5123 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005124
Kiran Kandi910e1862013-10-29 13:29:42 -07005125 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005126
5127 char value[PROPERTY_VALUE_MAX];
5128 int trial;
5129 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5130 trial = atoi(value);
5131 if (period_size_is_plausible_for_low_latency(trial)) {
5132 pcm_config_low_latency.period_size = trial;
5133 pcm_config_low_latency.start_threshold = trial / 4;
5134 pcm_config_low_latency.avail_min = trial / 4;
5135 configured_low_latency_capture_period_size = trial;
5136 }
5137 }
5138 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5139 trial = atoi(value);
5140 if (period_size_is_plausible_for_low_latency(trial)) {
5141 configured_low_latency_capture_period_size = trial;
5142 }
5143 }
5144
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005145 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5146 af_period_multiplier = atoi(value);
5147 if (af_period_multiplier < 0)
5148 af_period_multiplier = 2;
5149 else if (af_period_multiplier > 4)
5150 af_period_multiplier = 4;
5151
5152 ALOGV("new period_multiplier = %d", af_period_multiplier);
5153 }
5154
vivek mehta446c3962015-09-14 10:57:35 -07005155 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005156 pthread_mutex_unlock(&adev_init_lock);
5157
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005158 if (adev->adm_init)
5159 adev->adm_data = adev->adm_init();
5160
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305161 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305162 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005163 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 return 0;
5165}
5166
5167static struct hw_module_methods_t hal_module_methods = {
5168 .open = adev_open,
5169};
5170
5171struct audio_module HAL_MODULE_INFO_SYM = {
5172 .common = {
5173 .tag = HARDWARE_MODULE_TAG,
5174 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5175 .hal_api_version = HARDWARE_HAL_API_VERSION,
5176 .id = AUDIO_HARDWARE_MODULE_ID,
5177 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005178 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005179 .methods = &hal_module_methods,
5180 },
5181};