blob: e554d86ef1550f59d0d0d83ea6e0888cf0c51018 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
609static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
610{
611 ALOGV("%s snd device %d", __func__, snd_device);
612 int new_backend_idx = platform_get_backend_index(snd_device);
613
614 if (((new_backend_idx == HEADPHONE_BACKEND) ||
615 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
616 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
617 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618 struct listnode *node = NULL;
619 struct audio_usecase *uc = NULL;
620 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530622
623 list_for_each(node, &adev->usecase_list) {
624 uc = node_to_item(node, struct audio_usecase, list);
625 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530626 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530627 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
628
629 if((new_backend_idx == HEADPHONE_BACKEND) &&
630 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
631 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530632 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
633 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530634 enable_asrc_mode(adev);
635 break;
636 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
637 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
638 (usecase_backend_idx == HEADPHONE_BACKEND)) {
639 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
640 __func__);
641 disable_audio_route(adev, uc);
642 disable_snd_device(adev, uc->out_snd_device);
643 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
644 if (new_backend_idx == DSD_NATIVE_BACKEND)
645 audio_route_apply_and_update_path(adev->audio_route,
646 "hph-true-highquality-mode");
647 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
648 (curr_out->bit_width >= 24))
649 audio_route_apply_and_update_path(adev->audio_route,
650 "hph-highquality-mode");
651 enable_asrc_mode(adev);
652 enable_snd_device(adev, uc->out_snd_device);
653 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530654 break;
655 }
656 }
657 }
658 }
659}
660
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700661int pcm_ioctl(struct pcm *pcm, int request, ...)
662{
663 va_list ap;
664 void * arg;
665 int pcm_fd = *(int*)pcm;
666
667 va_start(ap, request);
668 arg = va_arg(ap, void *);
669 va_end(ap);
670
671 return ioctl(pcm_fd, request, arg);
672}
673
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700674int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700675 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800676{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700678 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800679
680 if (usecase == NULL)
681 return -EINVAL;
682
683 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
684
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800685 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800687 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800689
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800690#ifdef DS1_DOLBY_DAP_ENABLED
691 audio_extn_dolby_set_dmid(adev);
692 audio_extn_dolby_set_endpoint(adev);
693#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700694 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700695 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530696 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700697 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530698 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800699 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700700 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700701 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700702 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703 ALOGV("%s: exit", __func__);
704 return 0;
705}
706
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700707int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700708 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700711 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530713 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 return -EINVAL;
715
716 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 if (usecase->type == PCM_CAPTURE)
718 snd_device = usecase->in_snd_device;
719 else
720 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800721 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700722 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700723 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700724 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700725 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530726 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727 ALOGV("%s: exit", __func__);
728 return 0;
729}
730
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700731int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530734 int i, num_devices = 0;
735 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700736 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
737
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800738 if (snd_device < SND_DEVICE_MIN ||
739 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800740 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800741 return -EINVAL;
742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700743
744 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700745
746 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
747 ALOGE("%s: Invalid sound device returned", __func__);
748 return -EINVAL;
749 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700751 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700752 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 return 0;
754 }
755
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530756
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700757 if (audio_extn_spkr_prot_is_enabled())
758 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700759
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800760 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
761 audio_extn_spkr_prot_is_enabled()) {
762 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700763 adev->snd_dev_ref_cnt[snd_device]--;
764 return -EINVAL;
765 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200766 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800767 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800768 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200769 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800770 return -EINVAL;
771 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700772 } else if (platform_split_snd_device(adev->platform,
773 snd_device,
774 &num_devices,
775 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530776 for (i = 0; i < num_devices; i++) {
777 enable_snd_device(adev, new_snd_devices[i]);
778 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800779 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700780 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530781
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530782 if (platform_check_codec_asrc_support(adev->platform))
783 check_and_set_asrc_mode(adev, snd_device);
784
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530785 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
786 (audio_extn_a2dp_start_playback() < 0)) {
787 ALOGE(" fail to configure A2dp control path ");
788 return -EINVAL;
789 }
790
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700791 /* due to the possibility of calibration overwrite between listen
792 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700793 audio_extn_sound_trigger_update_device_status(snd_device,
794 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530795 audio_extn_listen_update_device_status(snd_device,
796 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700797 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700798 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700799 audio_extn_sound_trigger_update_device_status(snd_device,
800 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530801 audio_extn_listen_update_device_status(snd_device,
802 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700803 return -EINVAL;
804 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300805 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700806 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530807
808 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
809 !adev->native_playback_enabled &&
810 audio_is_true_native_stream_active(adev)) {
811 ALOGD("%s: %d: napb: enabling native mode in hardware",
812 __func__, __LINE__);
813 audio_route_apply_and_update_path(adev->audio_route,
814 "true-native-mode");
815 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818 return 0;
819}
820
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700821int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700822 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800823{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530824 int i, num_devices = 0;
825 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700826 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
827
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800828 if (snd_device < SND_DEVICE_MIN ||
829 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800830 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800831 return -EINVAL;
832 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
834 ALOGE("%s: device ref cnt is already 0", __func__);
835 return -EINVAL;
836 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700837
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700839
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700840 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
841 ALOGE("%s: Invalid sound device returned", __func__);
842 return -EINVAL;
843 }
844
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700846 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530847
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800848 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
849 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700850 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700851 } else if (platform_split_snd_device(adev->platform,
852 snd_device,
853 &num_devices,
854 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530855 for (i = 0; i < num_devices; i++) {
856 disable_snd_device(adev, new_snd_devices[i]);
857 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300858 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700859 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300860 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700861
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530862 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
863 audio_extn_a2dp_stop_playback();
864
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700865 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530866 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
868 adev->native_playback_enabled) {
869 ALOGD("%s: %d: napb: disabling native mode in hardware",
870 __func__, __LINE__);
871 audio_route_reset_and_update_path(adev->audio_route,
872 "true-native-mode");
873 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530874 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
875 adev->asrc_mode_enabled) {
876 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530877 disable_asrc_mode(adev);
878 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530879 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530880
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200881 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700882 audio_extn_sound_trigger_update_device_status(snd_device,
883 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530884 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800885 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888 return 0;
889}
890
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700891/*
892 legend:
893 uc - existing usecase
894 new_uc - new usecase
895 d1, d11, d2 - SND_DEVICE enums
896 a1, a2 - corresponding ANDROID device enums
897 B1, B2 - backend strings
898
899case 1
900 uc->dev d1 (a1) B1
901 new_uc->dev d1 (a1), d2 (a2) B1, B2
902
903 resolution: disable and enable uc->dev on d1
904
905case 2
906 uc->dev d1 (a1) B1
907 new_uc->dev d11 (a1) B1
908
909 resolution: need to switch uc since d1 and d11 are related
910 (e.g. speaker and voice-speaker)
911 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
912
913case 3
914 uc->dev d1 (a1) B1
915 new_uc->dev d2 (a2) B2
916
917 resolution: no need to switch uc
918
919case 4
920 uc->dev d1 (a1) B1
921 new_uc->dev d2 (a2) B1
922
923 resolution: disable enable uc-dev on d2 since backends match
924 we cannot enable two streams on two different devices if they
925 share the same backend. e.g. if offload is on speaker device using
926 QUAD_MI2S backend and a low-latency stream is started on voice-handset
927 using the same backend, offload must also be switched to voice-handset.
928
929case 5
930 uc->dev d1 (a1) B1
931 new_uc->dev d1 (a1), d2 (a2) B1
932
933 resolution: disable enable uc-dev on d2 since backends match
934 we cannot enable two streams on two different devices if they
935 share the same backend.
936
937case 6
938 uc->dev d1 (a1) B1
939 new_uc->dev d2 (a1) B2
940
941 resolution: no need to switch
942
943case 7
944 uc->dev d1 (a1), d2 (a2) B1, B2
945 new_uc->dev d1 (a1) B1
946
947 resolution: no need to switch
948
949*/
950static snd_device_t derive_playback_snd_device(void * platform,
951 struct audio_usecase *uc,
952 struct audio_usecase *new_uc,
953 snd_device_t new_snd_device)
954{
955 audio_devices_t a1 = uc->stream.out->devices;
956 audio_devices_t a2 = new_uc->stream.out->devices;
957
958 snd_device_t d1 = uc->out_snd_device;
959 snd_device_t d2 = new_snd_device;
960
961 // Treat as a special case when a1 and a2 are not disjoint
962 if ((a1 != a2) && (a1 & a2)) {
963 snd_device_t d3[2];
964 int num_devices = 0;
965 int ret = platform_split_snd_device(platform,
966 popcount(a1) > 1 ? d1 : d2,
967 &num_devices,
968 d3);
969 if (ret < 0) {
970 if (ret != -ENOSYS) {
971 ALOGW("%s failed to split snd_device %d",
972 __func__,
973 popcount(a1) > 1 ? d1 : d2);
974 }
975 goto end;
976 }
977
978 // NB: case 7 is hypothetical and isn't a practical usecase yet.
979 // But if it does happen, we need to give priority to d2 if
980 // the combo devices active on the existing usecase share a backend.
981 // This is because we cannot have a usecase active on a combo device
982 // and a new usecase requests one device in this combo pair.
983 if (platform_check_backends_match(d3[0], d3[1])) {
984 return d2; // case 5
985 } else {
986 return d1; // case 1
987 }
988 } else {
989 if (platform_check_backends_match(d1, d2)) {
990 return d2; // case 2, 4
991 } else {
992 return d1; // case 6, 3
993 }
994 }
995
996end:
997 return d2; // return whatever was calculated before.
998}
999
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301001 struct audio_usecase *uc_info,
1002 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003{
1004 struct listnode *node;
1005 struct audio_usecase *usecase;
1006 bool switch_device[AUDIO_USECASE_MAX];
1007 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001008 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301009 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 /*
1011 * This function is to make sure that all the usecases that are active on
1012 * the hardware codec backend are always routed to any one device that is
1013 * handled by the hardware codec.
1014 * For example, if low-latency and deep-buffer usecases are currently active
1015 * on speaker and out_set_parameters(headset) is received on low-latency
1016 * output, then we have to make sure deep-buffer is also switched to headset,
1017 * because of the limitation that both the devices cannot be enabled
1018 * at the same time as they share the same backend.
1019 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001020 /*
1021 * This call is to check if we need to force routing for a particular stream
1022 * If there is a backend configuration change for the device when a
1023 * new stream starts, then ADM needs to be closed and re-opened with the new
1024 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001025 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001026 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001027 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1028 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301029 /* For a2dp device reconfigure all active sessions
1030 * with new AFE encoder format based on a2dp state
1031 */
1032 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1033 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1034 audio_extn_a2dp_is_force_device_switch()) {
1035 force_routing = true;
1036 force_restart_session = true;
1037 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301038 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1039
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001041 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001042 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1044 switch_device[i] = false;
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001048
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301049 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1050 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301051 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301052 platform_get_snd_device_name(usecase->out_snd_device),
1053 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001054 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301055 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001056 (derive_playback_snd_device(adev->platform,
1057 usecase, uc_info,
1058 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301059 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1060 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301061 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301062 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1063 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1064 ((force_restart_session) ||
1065 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301066
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301067 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1068 __func__, use_case_table[usecase->id],
1069 platform_get_snd_device_name(usecase->out_snd_device));
1070 disable_audio_route(adev, usecase);
1071 switch_device[usecase->id] = true;
1072 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 }
1074 }
1075
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301076 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1077 num_uc_to_switch);
1078
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001080 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301082 /* Make sure the previous devices to be disabled first and then enable the
1083 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 list_for_each(node, &adev->usecase_list) {
1085 usecase = node_to_item(node, struct audio_usecase, list);
1086 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001087 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 }
1089 }
1090
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001091 list_for_each(node, &adev->usecase_list) {
1092 usecase = node_to_item(node, struct audio_usecase, list);
1093 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001094 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001095 }
1096 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 /* Re-route all the usecases on the shared backend other than the
1099 specified usecase to new snd devices */
1100 list_for_each(node, &adev->usecase_list) {
1101 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301102 /* Update the out_snd_device only before enabling the audio route */
1103 if (switch_device[usecase->id]) {
1104 usecase->out_snd_device = snd_device;
1105 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301106 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301107 use_case_table[usecase->id],
1108 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001109 /* Update voc calibration before enabling VoIP route */
1110 if (usecase->type == VOIP_CALL)
1111 status = platform_switch_voice_call_device_post(adev->platform,
1112 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001113 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301114 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 }
1117 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118 }
1119}
1120
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301121static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001122 struct audio_usecase *uc_info,
1123 snd_device_t snd_device)
1124{
1125 struct listnode *node;
1126 struct audio_usecase *usecase;
1127 bool switch_device[AUDIO_USECASE_MAX];
1128 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301129 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001130 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001131
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301132 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1133 snd_device);
1134 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301135
1136 /*
1137 * Make sure out devices is checked against out codec backend device and
1138 * also in devices against in codec backend. Checking out device against in
1139 * codec backend or vice versa causes issues.
1140 */
1141 if (uc_info->type == PCM_CAPTURE)
1142 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001143 /*
1144 * This function is to make sure that all the active capture usecases
1145 * are always routed to the same input sound device.
1146 * For example, if audio-record and voice-call usecases are currently
1147 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1148 * is received for voice call then we have to make sure that audio-record
1149 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1150 * because of the limitation that two devices cannot be enabled
1151 * at the same time if they share the same backend.
1152 */
1153 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1154 switch_device[i] = false;
1155
1156 list_for_each(node, &adev->usecase_list) {
1157 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301158 /*
1159 * TODO: Enhance below condition to handle BT sco/USB multi recording
1160 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001161 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301163 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301164 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301165 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001166 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001167 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1169 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001170 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001171 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001172 switch_device[usecase->id] = true;
1173 num_uc_to_switch++;
1174 }
1175 }
1176
1177 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001178 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301180 /* Make sure the previous devices to be disabled first and then enable the
1181 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001182 list_for_each(node, &adev->usecase_list) {
1183 usecase = node_to_item(node, struct audio_usecase, list);
1184 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001185 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001186 }
1187 }
1188
1189 list_for_each(node, &adev->usecase_list) {
1190 usecase = node_to_item(node, struct audio_usecase, list);
1191 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001192 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001193 }
1194 }
1195
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001196 /* Re-route all the usecases on the shared backend other than the
1197 specified usecase to new snd devices */
1198 list_for_each(node, &adev->usecase_list) {
1199 usecase = node_to_item(node, struct audio_usecase, list);
1200 /* Update the in_snd_device only before enabling the audio route */
1201 if (switch_device[usecase->id] ) {
1202 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001203 if (usecase->type != VOICE_CALL) {
1204 /* Update voc calibration before enabling VoIP route */
1205 if (usecase->type == VOIP_CALL)
1206 status = platform_switch_voice_call_device_post(adev->platform,
1207 usecase->out_snd_device,
1208 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301209 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001210 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001211 }
1212 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 }
1214}
1215
Mingming Yin3a941d42016-02-17 18:08:05 -08001216static void reset_hdmi_sink_caps(struct stream_out *out) {
1217 int i = 0;
1218
1219 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1220 out->supported_channel_masks[i] = 0;
1221 }
1222 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1223 out->supported_formats[i] = 0;
1224 }
1225 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1226 out->supported_sample_rates[i] = 0;
1227 }
1228}
1229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001231static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Mingming Yin3a941d42016-02-17 18:08:05 -08001233 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001234 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235
Mingming Yin3a941d42016-02-17 18:08:05 -08001236 reset_hdmi_sink_caps(out);
1237
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001238 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001239 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001240 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001241 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001242 }
1243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001246 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001247 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001248 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1249 case 6:
1250 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1251 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1252 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1253 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1254 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1255 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256 break;
1257 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001258 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001259 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001260 break;
1261 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001262
1263 // check channel format caps
1264 i = 0;
1265 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1266 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1267 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1268 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1269 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1270 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1271 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1272 }
1273
1274 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1275 ALOGV(":%s HDMI supports DTS format", __func__);
1276 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1277 }
1278
1279 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1280 ALOGV(":%s HDMI supports DTS HD format", __func__);
1281 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1282 }
1283
1284
1285 // check sample rate caps
1286 i = 0;
1287 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1288 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1289 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1290 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1291 }
1292 }
1293
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001294 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295}
1296
Alexy Josephb1379942016-01-29 15:49:38 -08001297audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001298 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001299{
1300 struct audio_usecase *usecase;
1301 struct listnode *node;
1302
1303 list_for_each(node, &adev->usecase_list) {
1304 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001305 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001306 ALOGV("%s: usecase id %d", __func__, usecase->id);
1307 return usecase->id;
1308 }
1309 }
1310 return USECASE_INVALID;
1311}
1312
Alexy Josephb1379942016-01-29 15:49:38 -08001313struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001314 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315{
1316 struct audio_usecase *usecase;
1317 struct listnode *node;
1318
1319 list_for_each(node, &adev->usecase_list) {
1320 usecase = node_to_item(node, struct audio_usecase, list);
1321 if (usecase->id == uc_id)
1322 return usecase;
1323 }
1324 return NULL;
1325}
1326
Dhananjay Kumard4833242016-10-06 22:09:12 +05301327struct stream_in *get_next_active_input(const struct audio_device *adev)
1328{
1329 struct audio_usecase *usecase;
1330 struct listnode *node;
1331
1332 list_for_each_reverse(node, &adev->usecase_list) {
1333 usecase = node_to_item(node, struct audio_usecase, list);
1334 if (usecase->type == PCM_CAPTURE)
1335 return usecase->stream.in;
1336 }
1337 return NULL;
1338}
1339
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301340/*
1341 * is a true native playback active
1342 */
1343bool audio_is_true_native_stream_active(struct audio_device *adev)
1344{
1345 bool active = false;
1346 int i = 0;
1347 struct listnode *node;
1348
1349 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1350 ALOGV("%s:napb: not in true mode or non hdphones device",
1351 __func__);
1352 active = false;
1353 goto exit;
1354 }
1355
1356 list_for_each(node, &adev->usecase_list) {
1357 struct audio_usecase *uc;
1358 uc = node_to_item(node, struct audio_usecase, list);
1359 struct stream_out *curr_out =
1360 (struct stream_out*) uc->stream.out;
1361
1362 if (curr_out && PCM_PLAYBACK == uc->type) {
1363 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1364 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1365 uc->id, curr_out->sample_rate,
1366 curr_out->bit_width,
1367 platform_get_snd_device_name(uc->out_snd_device));
1368
1369 if (is_offload_usecase(uc->id) &&
1370 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1371 active = true;
1372 ALOGD("%s:napb:native stream detected", __func__);
1373 }
1374 }
1375 }
1376exit:
1377 return active;
1378}
1379
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301380/*
1381 * if native DSD playback active
1382 */
1383bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1384{
1385 bool active = false;
1386 struct listnode *node = NULL;
1387 struct audio_usecase *uc = NULL;
1388 struct stream_out *curr_out = NULL;
1389
1390 list_for_each(node, &adev->usecase_list) {
1391 uc = node_to_item(node, struct audio_usecase, list);
1392 curr_out = (struct stream_out*) uc->stream.out;
1393
1394 if (curr_out && PCM_PLAYBACK == uc->type &&
1395 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1396 active = true;
1397 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301398 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301399 }
1400 }
1401 return active;
1402}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301403
1404static bool force_device_switch(struct audio_usecase *usecase)
1405{
1406 bool ret = false;
1407 bool is_it_true_mode = false;
1408
1409 if (is_offload_usecase(usecase->id) &&
1410 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001411 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1412 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1413 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301414 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1415 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1416 (!is_it_true_mode && adev->native_playback_enabled)){
1417 ret = true;
1418 ALOGD("napb: time to toggle native mode");
1419 }
1420 }
1421
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301422 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301423 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1424 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301425 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001426 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301427 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301428 ALOGD("Force a2dp device switch to update new encoder config");
1429 ret = true;
1430 }
1431
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301432 return ret;
1433}
1434
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001435int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001437 snd_device_t out_snd_device = SND_DEVICE_NONE;
1438 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 struct audio_usecase *usecase = NULL;
1440 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001441 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001442 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001443 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301446 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 usecase = get_usecase_from_list(adev, uc_id);
1449 if (usecase == NULL) {
1450 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1451 return -EINVAL;
1452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001454 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001455 (usecase->type == VOIP_CALL) ||
1456 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301457 if(usecase->stream.out == NULL) {
1458 ALOGE("%s: stream.out is NULL", __func__);
1459 return -EINVAL;
1460 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001461 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001462 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001463 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 usecase->devices = usecase->stream.out->devices;
1465 } else {
1466 /*
1467 * If the voice call is active, use the sound devices of voice call usecase
1468 * so that it would not result any device switch. All the usecases will
1469 * be switched to new device when select_devices() is called for voice call
1470 * usecase. This is to avoid switching devices for voice call when
1471 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001472 * choose voice call device only if the use case device is
1473 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001475 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001476 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001477 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001478 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1479 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301480 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1481 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001482 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 in_snd_device = vc_usecase->in_snd_device;
1484 out_snd_device = vc_usecase->out_snd_device;
1485 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001486 } else if (voice_extn_compress_voip_is_active(adev)) {
1487 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001488 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001489 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1490 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001491 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001492 in_snd_device = voip_usecase->in_snd_device;
1493 out_snd_device = voip_usecase->out_snd_device;
1494 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001495 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001496 hfp_ucid = audio_extn_hfp_get_usecase();
1497 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001498 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001499 in_snd_device = hfp_usecase->in_snd_device;
1500 out_snd_device = hfp_usecase->out_snd_device;
1501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 }
1503 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301504 if (usecase->stream.out == NULL) {
1505 ALOGE("%s: stream.out is NULL", __func__);
1506 return -EINVAL;
1507 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 usecase->devices = usecase->stream.out->devices;
1509 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001510 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001511 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001512 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001513 if (usecase->stream.out == adev->primary_output &&
1514 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001515 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001516 select_devices(adev, adev->active_input->usecase);
1517 }
1518 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301520 if (usecase->stream.in == NULL) {
1521 ALOGE("%s: stream.in is NULL", __func__);
1522 return -EINVAL;
1523 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524 usecase->devices = usecase->stream.in->device;
1525 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001526 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001527 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001528 if (adev->active_input &&
1529 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301530 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1531 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1532 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001533 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001534 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001535 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1536 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001537 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001538 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001539 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540 }
1541 }
1542
1543 if (out_snd_device == usecase->out_snd_device &&
1544 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301545
1546 if (!force_device_switch(usecase))
1547 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 }
1549
sangwoobc677242013-08-08 16:53:43 +09001550 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001551 out_snd_device, platform_get_snd_device_name(out_snd_device),
1552 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 /*
1555 * Limitation: While in call, to do a device switch we need to disable
1556 * and enable both RX and TX devices though one of them is same as current
1557 * device.
1558 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001559 if ((usecase->type == VOICE_CALL) &&
1560 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1561 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001562 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001563 }
1564
1565 if (((usecase->type == VOICE_CALL) ||
1566 (usecase->type == VOIP_CALL)) &&
1567 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1568 /* Disable sidetone only if voice/voip call already exists */
1569 if (voice_is_call_state_active(adev) ||
1570 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001571 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001572
1573 /* Disable aanc only if voice call exists */
1574 if (voice_is_call_state_active(adev))
1575 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001576 }
1577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 /* Disable current sound devices */
1579 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001580 disable_audio_route(adev, usecase);
1581 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001585 disable_audio_route(adev, usecase);
1586 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 }
1588
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001589 /* Applicable only on the targets that has external modem.
1590 * New device information should be sent to modem before enabling
1591 * the devices to reduce in-call device switch time.
1592 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001593 if ((usecase->type == VOICE_CALL) &&
1594 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1595 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001596 status = platform_switch_voice_call_enable_device_config(adev->platform,
1597 out_snd_device,
1598 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001599 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001600
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 /* Enable new sound devices */
1602 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001603 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 }
1606
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001607 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301608 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001609 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611
Avinash Vaish71a8b972014-07-24 15:36:33 +05301612 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001613 status = platform_switch_voice_call_device_post(adev->platform,
1614 out_snd_device,
1615 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301616 enable_audio_route_for_voice_usecases(adev, usecase);
1617 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001618
sangwoo170731f2013-06-08 15:36:36 +09001619 usecase->in_snd_device = in_snd_device;
1620 usecase->out_snd_device = out_snd_device;
1621
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301622 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1623 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301624 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001625 if ((24 == usecase->stream.out->bit_width) &&
1626 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1627 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1628 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1629 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1630 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1631 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1632 /*
1633 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1634 * configured device sample rate, if not update the COPP rate to be equal to the
1635 * device sample rate, else open COPP at stream sample rate
1636 */
1637 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1638 usecase->stream.out->sample_rate,
1639 &usecase->stream.out->app_type_cfg.sample_rate);
1640 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1641 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1642 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1643 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1644 }
1645
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001646 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001647 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001648 audio_extn_gef_notify_device_config(
1649 usecase->stream.out->devices,
1650 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001651 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001652 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001653 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301654 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001655 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001656
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001657 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001658 /* Enable aanc only if voice call exists */
1659 if (voice_is_call_state_active(adev))
1660 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1661
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001662 /* Enable sidetone only if other voice/voip call already exists */
1663 if (voice_is_call_state_active(adev) ||
1664 voice_extn_compress_voip_is_started(adev))
1665 voice_set_sidetone(adev, out_snd_device, true);
1666 }
1667
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001668 /* Applicable only on the targets that has external modem.
1669 * Enable device command should be sent to modem only after
1670 * enabling voice call mixer controls
1671 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001672 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001673 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1674 out_snd_device,
1675 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301676 ALOGD("%s: done",__func__);
1677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 return status;
1679}
1680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681static int stop_input_stream(struct stream_in *in)
1682{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301683 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 struct audio_usecase *uc_info;
1685 struct audio_device *adev = in->dev;
1686
Eric Laurent994a6932013-07-17 11:51:42 -07001687 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001688 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 uc_info = get_usecase_from_list(adev, in->usecase);
1690 if (uc_info == NULL) {
1691 ALOGE("%s: Could not find the usecase (%d) in the list",
1692 __func__, in->usecase);
1693 return -EINVAL;
1694 }
1695
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001696 /* Close in-call recording streams */
1697 voice_check_and_stop_incall_rec_usecase(adev, in);
1698
Eric Laurent150dbfe2013-02-27 14:31:02 -08001699 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001700 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701
1702 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001703 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001705 list_remove(&uc_info->list);
1706 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001708 adev->active_input = get_next_active_input(adev);
1709
Eric Laurent994a6932013-07-17 11:51:42 -07001710 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 return ret;
1712}
1713
1714int start_input_stream(struct stream_in *in)
1715{
1716 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001717 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 struct audio_usecase *uc_info;
1719 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301720 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721
Mingming Yin2664a5b2015-09-03 10:53:11 -07001722 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1723 if (get_usecase_from_list(adev, usecase) == NULL)
1724 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301725 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1726 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001727
Naresh Tanniru80659832014-06-04 18:17:56 +05301728
1729 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301730 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301731 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301732 goto error_config;
1733 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301734
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001735 /* Check if source matches incall recording usecase criteria */
1736 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1737 if (ret)
1738 goto error_config;
1739 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001740 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1741
1742 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1743 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1744 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001745 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001746 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001747
Eric Laurentb23d5282013-05-14 15:27:20 -07001748 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 if (in->pcm_device_id < 0) {
1750 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1751 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001752 ret = -EINVAL;
1753 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755
1756 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001758
1759 if (!uc_info) {
1760 ret = -ENOMEM;
1761 goto error_config;
1762 }
1763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764 uc_info->id = in->usecase;
1765 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001766 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 uc_info->devices = in->device;
1768 uc_info->in_snd_device = SND_DEVICE_NONE;
1769 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001771 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301772 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1773 adev->perf_lock_opts,
1774 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301777 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1778 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001779
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301780 if (audio_extn_cin_attached_usecase(in->usecase)) {
1781 ret = audio_extn_cin_start_input_stream(in);
1782 if (ret)
1783 goto error_open;
1784 else
1785 goto done_open;
1786 }
1787
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001788 unsigned int flags = PCM_IN;
1789 unsigned int pcm_open_retry_count = 0;
1790
1791 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1792 flags |= PCM_MMAP | PCM_NOIRQ;
1793 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001794 } else if (in->realtime) {
1795 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001796 }
1797
1798 while (1) {
1799 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1800 flags, &in->config);
1801 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1802 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1803 if (in->pcm != NULL) {
1804 pcm_close(in->pcm);
1805 in->pcm = NULL;
1806 }
1807 if (pcm_open_retry_count-- == 0) {
1808 ret = -EIO;
1809 goto error_open;
1810 }
1811 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1812 continue;
1813 }
1814 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001816
1817 ALOGV("%s: pcm_prepare", __func__);
1818 ret = pcm_prepare(in->pcm);
1819 if (ret < 0) {
1820 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1821 pcm_close(in->pcm);
1822 in->pcm = NULL;
1823 goto error_open;
1824 }
1825
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001826 register_in_stream(in);
1827 if (in->realtime) {
1828 ret = pcm_start(in->pcm);
1829 if (ret < 0)
1830 goto error_open;
1831 }
1832
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301833done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301834 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001835 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001836
Eric Laurentc8400632013-02-14 19:04:54 -08001837 return ret;
1838
1839error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301840 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001842error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301843 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301844 /*
1845 * sleep 50ms to allow sufficient time for kernel
1846 * drivers to recover incases like SSR.
1847 */
1848 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001849 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001850
1851 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852}
1853
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001854void lock_input_stream(struct stream_in *in)
1855{
1856 pthread_mutex_lock(&in->pre_lock);
1857 pthread_mutex_lock(&in->lock);
1858 pthread_mutex_unlock(&in->pre_lock);
1859}
1860
1861void lock_output_stream(struct stream_out *out)
1862{
1863 pthread_mutex_lock(&out->pre_lock);
1864 pthread_mutex_lock(&out->lock);
1865 pthread_mutex_unlock(&out->pre_lock);
1866}
1867
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868/* must be called with out->lock locked */
1869static int send_offload_cmd_l(struct stream_out* out, int command)
1870{
1871 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1872
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001873 if (!cmd) {
1874 ALOGE("failed to allocate mem for command 0x%x", command);
1875 return -ENOMEM;
1876 }
1877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 ALOGVV("%s %d", __func__, command);
1879
1880 cmd->cmd = command;
1881 list_add_tail(&out->offload_cmd_list, &cmd->node);
1882 pthread_cond_signal(&out->offload_cond);
1883 return 0;
1884}
1885
1886/* must be called iwth out->lock locked */
1887static void stop_compressed_output_l(struct stream_out *out)
1888{
1889 out->offload_state = OFFLOAD_STATE_IDLE;
1890 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892 if (out->compr != NULL) {
1893 compress_stop(out->compr);
1894 while (out->offload_thread_blocked) {
1895 pthread_cond_wait(&out->cond, &out->lock);
1896 }
1897 }
1898}
1899
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001900bool is_offload_usecase(audio_usecase_t uc_id)
1901{
1902 unsigned int i;
1903 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1904 if (uc_id == offload_usecases[i])
1905 return true;
1906 }
1907 return false;
1908}
1909
vivek mehta446c3962015-09-14 10:57:35 -07001910static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001911{
vivek mehta446c3962015-09-14 10:57:35 -07001912 audio_usecase_t ret_uc = USECASE_INVALID;
1913 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001914 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001915 if (!adev->multi_offload_enable) {
1916 if (is_direct_pcm)
1917 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1918 else
1919 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001920
vivek mehta446c3962015-09-14 10:57:35 -07001921 pthread_mutex_lock(&adev->lock);
1922 if (get_usecase_from_list(adev, ret_uc) != NULL)
1923 ret_uc = USECASE_INVALID;
1924 pthread_mutex_unlock(&adev->lock);
1925
1926 return ret_uc;
1927 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001928
1929 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001930 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1931 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1932 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1933 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001934 break;
1935 }
1936 }
vivek mehta446c3962015-09-14 10:57:35 -07001937
1938 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1939 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001940}
1941
1942static void free_offload_usecase(struct audio_device *adev,
1943 audio_usecase_t uc_id)
1944{
vivek mehta446c3962015-09-14 10:57:35 -07001945 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001946 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001947
1948 if (!adev->multi_offload_enable)
1949 return;
1950
1951 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1952 if (offload_usecases[offload_uc_index] == uc_id) {
1953 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001954 break;
1955 }
1956 }
1957 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1958}
1959
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960static void *offload_thread_loop(void *context)
1961{
1962 struct stream_out *out = (struct stream_out *) context;
1963 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001964 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1967 set_sched_policy(0, SP_FOREGROUND);
1968 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1969
1970 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001971 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 for (;;) {
1973 struct offload_cmd *cmd = NULL;
1974 stream_callback_event_t event;
1975 bool send_callback = false;
1976
1977 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1978 __func__, list_empty(&out->offload_cmd_list),
1979 out->offload_state);
1980 if (list_empty(&out->offload_cmd_list)) {
1981 ALOGV("%s SLEEPING", __func__);
1982 pthread_cond_wait(&out->offload_cond, &out->lock);
1983 ALOGV("%s RUNNING", __func__);
1984 continue;
1985 }
1986
1987 item = list_head(&out->offload_cmd_list);
1988 cmd = node_to_item(item, struct offload_cmd, node);
1989 list_remove(item);
1990
1991 ALOGVV("%s STATE %d CMD %d out->compr %p",
1992 __func__, out->offload_state, cmd->cmd, out->compr);
1993
1994 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1995 free(cmd);
1996 break;
1997 }
1998
1999 if (out->compr == NULL) {
2000 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002001 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002002 pthread_cond_signal(&out->cond);
2003 continue;
2004 }
2005 out->offload_thread_blocked = true;
2006 pthread_mutex_unlock(&out->lock);
2007 send_callback = false;
2008 switch(cmd->cmd) {
2009 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002010 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002012 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 send_callback = true;
2014 event = STREAM_CBK_EVENT_WRITE_READY;
2015 break;
2016 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002017 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302018 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002019 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302020 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002021 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302022 if (ret < 0)
2023 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302024 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302025 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002026 compress_drain(out->compr);
2027 else
2028 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302029 if (ret != -ENETRESET) {
2030 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302031 pthread_mutex_lock(&out->lock);
2032 out->send_new_metadata = 1;
2033 out->send_next_track_params = true;
2034 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302035 event = STREAM_CBK_EVENT_DRAIN_READY;
2036 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2037 } else
2038 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 break;
2040 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002041 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002043 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 send_callback = true;
2045 event = STREAM_CBK_EVENT_DRAIN_READY;
2046 break;
2047 default:
2048 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2049 break;
2050 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002051 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 out->offload_thread_blocked = false;
2053 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002054 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002055 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002057 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 free(cmd);
2059 }
2060
2061 pthread_cond_signal(&out->cond);
2062 while (!list_empty(&out->offload_cmd_list)) {
2063 item = list_head(&out->offload_cmd_list);
2064 list_remove(item);
2065 free(node_to_item(item, struct offload_cmd, node));
2066 }
2067 pthread_mutex_unlock(&out->lock);
2068
2069 return NULL;
2070}
2071
2072static int create_offload_callback_thread(struct stream_out *out)
2073{
2074 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2075 list_init(&out->offload_cmd_list);
2076 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2077 offload_thread_loop, out);
2078 return 0;
2079}
2080
2081static int destroy_offload_callback_thread(struct stream_out *out)
2082{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002083 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 stop_compressed_output_l(out);
2085 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2086
2087 pthread_mutex_unlock(&out->lock);
2088 pthread_join(out->offload_thread, (void **) NULL);
2089 pthread_cond_destroy(&out->offload_cond);
2090
2091 return 0;
2092}
2093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094static int stop_output_stream(struct stream_out *out)
2095{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302096 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 struct audio_usecase *uc_info;
2098 struct audio_device *adev = out->dev;
2099
Eric Laurent994a6932013-07-17 11:51:42 -07002100 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002101 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 uc_info = get_usecase_from_list(adev, out->usecase);
2103 if (uc_info == NULL) {
2104 ALOGE("%s: Could not find the usecase (%d) in the list",
2105 __func__, out->usecase);
2106 return -EINVAL;
2107 }
2108
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002109 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302110 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002111 if (adev->visualizer_stop_output != NULL)
2112 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002113
2114 audio_extn_dts_remove_state_notifier_node(out->usecase);
2115
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002116 if (adev->offload_effects_stop_output != NULL)
2117 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2118 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002119
Eric Laurent150dbfe2013-02-27 14:31:02 -08002120 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002121 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002122
2123 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002124 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002126 list_remove(&uc_info->list);
2127 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302130 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002131 ALOGV("Disable passthrough , reset mixer to pcm");
2132 /* NO_PASSTHROUGH */
2133 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002134 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002135 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2136 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002137
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302138 /* Must be called after removing the usecase from list */
2139 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302140 audio_extn_keep_alive_start();
2141
Eric Laurent994a6932013-07-17 11:51:42 -07002142 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 return ret;
2144}
2145
2146int start_output_stream(struct stream_out *out)
2147{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 struct audio_usecase *uc_info;
2150 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302151 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002153 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2154 ret = -EINVAL;
2155 goto error_config;
2156 }
2157
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302158 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2159 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2160 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302161
Naresh Tanniru80659832014-06-04 18:17:56 +05302162 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302163 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302164 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165 goto error_config;
2166 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302167
Eric Laurentb23d5282013-05-14 15:27:20 -07002168 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 if (out->pcm_device_id < 0) {
2170 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2171 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002172 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002173 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 }
2175
2176 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002177
2178 if (!uc_info) {
2179 ret = -ENOMEM;
2180 goto error_config;
2181 }
2182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 uc_info->id = out->usecase;
2184 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002185 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002186 uc_info->devices = out->devices;
2187 uc_info->in_snd_device = SND_DEVICE_NONE;
2188 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002189 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302191 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2192 adev->perf_lock_opts,
2193 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302194
2195 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2196 audio_extn_keep_alive_stop();
2197 if (audio_extn_passthru_is_enabled() &&
2198 audio_extn_passthru_is_passthrough_stream(out)) {
2199 audio_extn_passthru_on_start(out);
2200 audio_extn_passthru_update_stream_configuration(adev, out);
2201 }
2202 }
2203
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002204 select_devices(adev, out->usecase);
2205
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002206 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2207 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002208 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002209 unsigned int flags = PCM_OUT;
2210 unsigned int pcm_open_retry_count = 0;
2211 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2212 flags |= PCM_MMAP | PCM_NOIRQ;
2213 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002214 } else if (out->realtime) {
2215 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002216 } else
2217 flags |= PCM_MONOTONIC;
2218
2219 while (1) {
2220 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2221 flags, &out->config);
2222 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2223 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2224 if (out->pcm != NULL) {
2225 pcm_close(out->pcm);
2226 out->pcm = NULL;
2227 }
2228 if (pcm_open_retry_count-- == 0) {
2229 ret = -EIO;
2230 goto error_open;
2231 }
2232 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2233 continue;
2234 }
2235 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002236 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002237
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002238 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2239 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002240
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002241 ALOGV("%s: pcm_prepare", __func__);
2242 if (pcm_is_ready(out->pcm)) {
2243 ret = pcm_prepare(out->pcm);
2244 if (ret < 0) {
2245 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2246 pcm_close(out->pcm);
2247 out->pcm = NULL;
2248 goto error_open;
2249 }
2250 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002252 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2253 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002255 out->compr = compress_open(adev->snd_card,
2256 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 COMPRESS_IN, &out->compr_config);
2258 if (out->compr && !is_compress_ready(out->compr)) {
2259 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2260 compress_close(out->compr);
2261 out->compr = NULL;
2262 ret = -EIO;
2263 goto error_open;
2264 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302265 /* compress_open sends params of the track, so reset the flag here */
2266 out->is_compr_metadata_avail = false;
2267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 if (out->offload_callback)
2269 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002270
Fred Oh3f43e742015-03-04 18:42:34 -08002271 /* Since small bufs uses blocking writes, a write will be blocked
2272 for the default max poll time (20s) in the event of an SSR.
2273 Reduce the poll time to observe and deal with SSR faster.
2274 */
Ashish Jain5106d362016-05-11 19:23:33 +05302275 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002276 compress_set_max_poll_wait(out->compr, 1000);
2277 }
2278
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002279 audio_extn_dts_create_state_notifier_node(out->usecase);
2280 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2281 popcount(out->channel_mask),
2282 out->playback_started);
2283
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002284#ifdef DS1_DOLBY_DDP_ENABLED
2285 if (audio_extn_is_dolby_format(out->format))
2286 audio_extn_dolby_send_ddp_endp_params(adev);
2287#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302288 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002289 if (adev->visualizer_start_output != NULL)
2290 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2291 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302292 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002293 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002296
2297 if (ret == 0) {
2298 register_out_stream(out);
2299 if (out->realtime) {
2300 ret = pcm_start(out->pcm);
2301 if (ret < 0)
2302 goto error_open;
2303 }
2304 }
2305
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302306 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002307 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002308
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002309 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302311 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002313error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302314 /*
2315 * sleep 50ms to allow sufficient time for kernel
2316 * drivers to recover incases like SSR.
2317 */
2318 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320}
2321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322static int check_input_parameters(uint32_t sample_rate,
2323 audio_format_t format,
2324 int channel_count)
2325{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002326 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302328 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2329 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2330 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002331 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302332 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002333
2334 switch (channel_count) {
2335 case 1:
2336 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302337 case 3:
2338 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002339 case 6:
2340 break;
2341 default:
2342 ret = -EINVAL;
2343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
2345 switch (sample_rate) {
2346 case 8000:
2347 case 11025:
2348 case 12000:
2349 case 16000:
2350 case 22050:
2351 case 24000:
2352 case 32000:
2353 case 44100:
2354 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302355 case 96000:
2356 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 break;
2358 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002359 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 }
2361
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002362 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363}
2364
2365static size_t get_input_buffer_size(uint32_t sample_rate,
2366 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002367 int channel_count,
2368 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 size_t size = 0;
2371
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002372 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2373 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002375 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002376 if (is_low_latency)
2377 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302378
2379 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002381 /* make sure the size is multiple of 32 bytes
2382 * At 48 kHz mono 16-bit PCM:
2383 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2384 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2385 */
2386 size += 0x1f;
2387 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002388
2389 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390}
2391
Ashish Jain058165c2016-09-28 23:18:48 +05302392static size_t get_output_period_size(uint32_t sample_rate,
2393 audio_format_t format,
2394 int channel_count,
2395 int duration /*in millisecs*/)
2396{
2397 size_t size = 0;
2398 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2399
2400 if ((duration == 0) || (sample_rate == 0) ||
2401 (bytes_per_sample == 0) || (channel_count == 0)) {
2402 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2403 bytes_per_sample, channel_count);
2404 return -EINVAL;
2405 }
2406
2407 size = (sample_rate *
2408 duration *
2409 bytes_per_sample *
2410 channel_count) / 1000;
2411 /*
2412 * To have same PCM samples for all channels, the buffer size requires to
2413 * be multiple of (number of channels * bytes per sample)
2414 * For writes to succeed, the buffer must be written at address which is multiple of 32
2415 */
2416 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2417
2418 return (size/(channel_count * bytes_per_sample));
2419}
2420
Ashish Jain5106d362016-05-11 19:23:33 +05302421static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2422{
2423 uint64_t actual_frames_rendered = 0;
2424 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2425
2426 /* This adjustment accounts for buffering after app processor.
2427 * It is based on estimated DSP latency per use case, rather than exact.
2428 */
2429 int64_t platform_latency = platform_render_latency(out->usecase) *
2430 out->sample_rate / 1000000LL;
2431
2432 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2433 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2434 * hence only estimate.
2435 */
2436 int64_t signed_frames = out->written - kernel_buffer_size;
2437
2438 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2439
2440 if (signed_frames > 0)
2441 actual_frames_rendered = signed_frames;
2442
2443 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2444 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2445 (long long int)out->written, (int)kernel_buffer_size,
2446 audio_bytes_per_sample(out->compr_config.codec->format),
2447 popcount(out->channel_mask));
2448
2449 return actual_frames_rendered;
2450}
2451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2453{
2454 struct stream_out *out = (struct stream_out *)stream;
2455
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457}
2458
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002459static int out_set_sample_rate(struct audio_stream *stream __unused,
2460 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461{
2462 return -ENOSYS;
2463}
2464
2465static size_t out_get_buffer_size(const struct audio_stream *stream)
2466{
2467 struct stream_out *out = (struct stream_out *)stream;
2468
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002469 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002471 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2472 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302473 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302474 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002476 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002477 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478}
2479
2480static uint32_t out_get_channels(const struct audio_stream *stream)
2481{
2482 struct stream_out *out = (struct stream_out *)stream;
2483
2484 return out->channel_mask;
2485}
2486
2487static audio_format_t out_get_format(const struct audio_stream *stream)
2488{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 struct stream_out *out = (struct stream_out *)stream;
2490
2491 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492}
2493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002494static int out_set_format(struct audio_stream *stream __unused,
2495 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496{
2497 return -ENOSYS;
2498}
2499
2500static int out_standby(struct audio_stream *stream)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302505 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2506 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002508 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002510 if (adev->adm_deregister_stream)
2511 adev->adm_deregister_stream(adev->adm_data, out->handle);
2512
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002513 if (is_offload_usecase(out->usecase))
2514 stop_compressed_output_l(out);
2515
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002516 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002518 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2519 voice_extn_compress_voip_close_output_stream(stream);
2520 pthread_mutex_unlock(&adev->lock);
2521 pthread_mutex_unlock(&out->lock);
2522 ALOGD("VOIP output entered standby");
2523 return 0;
2524 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002525 if (out->pcm) {
2526 pcm_close(out->pcm);
2527 out->pcm = NULL;
2528 }
2529 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002530 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302531 out->send_next_track_params = false;
2532 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002533 out->gapless_mdata.encoder_delay = 0;
2534 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 if (out->compr != NULL) {
2536 compress_close(out->compr);
2537 out->compr = NULL;
2538 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002541 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 }
2543 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302544 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 return 0;
2546}
2547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002548static int out_dump(const struct audio_stream *stream __unused,
2549 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550{
2551 return 0;
2552}
2553
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002554static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2555{
2556 int ret = 0;
2557 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002558
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002559 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002560 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002561 return -EINVAL;
2562 }
2563
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302564 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002565
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002566 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2567 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302568 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002569 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002570 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2571 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302572 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002573 }
2574
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002575 ALOGV("%s new encoder delay %u and padding %u", __func__,
2576 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2577
2578 return 0;
2579}
2580
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002581static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2582{
2583 return out == adev->primary_output || out == adev->voice_tx_output;
2584}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2587{
2588 struct stream_out *out = (struct stream_out *)stream;
2589 struct audio_device *adev = out->dev;
2590 struct str_parms *parms;
2591 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002592 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
sangwoobc677242013-08-08 16:53:43 +09002594 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002595 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302597 if (!parms)
2598 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002599 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2600 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002602 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002603 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002605 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002606 * When HDMI cable is unplugged the music playback is paused and
2607 * the policy manager sends routing=0. But the audioflinger continues
2608 * to write data until standby time (3sec). As the HDMI core is
2609 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002610 * Avoid this by routing audio to speaker until standby.
2611 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002612 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2613 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302614 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002615 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2616 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002617 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302618 /*
2619 * When A2DP is disconnected the
2620 * music playback is paused and the policy manager sends routing=0
2621 * But the audioflingercontinues to write data until standby time
2622 * (3sec). As BT is turned off, the write gets blocked.
2623 * Avoid this by routing audio to speaker until standby.
2624 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002625 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302626 (val == AUDIO_DEVICE_NONE)) {
2627 val = AUDIO_DEVICE_OUT_SPEAKER;
2628 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302629 /* To avoid a2dp to sco overlapping force route BT usecases
2630 * to speaker based on Phone state
2631 */
Ashish Jainc597d102016-12-12 10:31:34 +05302632 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2633 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2634 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2635 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302636 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2637 (adev->mode == AUDIO_MODE_IN_CALL))) {
2638 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2639 val = AUDIO_DEVICE_OUT_SPEAKER;
2640 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002641 /*
2642 * select_devices() call below switches all the usecases on the same
2643 * backend to the new device. Refer to check_usecases_codec_backend() in
2644 * the select_devices(). But how do we undo this?
2645 *
2646 * For example, music playback is active on headset (deep-buffer usecase)
2647 * and if we go to ringtones and select a ringtone, low-latency usecase
2648 * will be started on headset+speaker. As we can't enable headset+speaker
2649 * and headset devices at the same time, select_devices() switches the music
2650 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2651 * So when the ringtone playback is completed, how do we undo the same?
2652 *
2653 * We are relying on the out_set_parameters() call on deep-buffer output,
2654 * once the ringtone playback is ended.
2655 * NOTE: We should not check if the current devices are same as new devices.
2656 * Because select_devices() must be called to switch back the music
2657 * playback to headset.
2658 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002659 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002660 audio_devices_t new_dev = val;
2661 bool same_dev = out->devices == new_dev;
2662 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002663
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002664 if (output_drives_call(adev, out)) {
2665 if(!voice_is_in_call(adev)) {
2666 if (adev->mode == AUDIO_MODE_IN_CALL) {
2667 adev->current_call_output = out;
2668 ret = voice_start_call(adev);
2669 }
2670 } else {
2671 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002672 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002673 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002674 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002675
2676 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002677 if (!same_dev) {
2678 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302679 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2680 adev->perf_lock_opts,
2681 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002682 if (adev->adm_on_routing_change)
2683 adev->adm_on_routing_change(adev->adm_data,
2684 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002685 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002686 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302687 if (!same_dev)
2688 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002689 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002690 }
2691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002693 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002695
2696 if (out == adev->primary_output) {
2697 pthread_mutex_lock(&adev->lock);
2698 audio_extn_set_parameters(adev, parms);
2699 pthread_mutex_unlock(&adev->lock);
2700 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002701 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002702 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002703 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002704
2705 audio_extn_dts_create_state_notifier_node(out->usecase);
2706 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2707 popcount(out->channel_mask),
2708 out->playback_started);
2709
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002710 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002711 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002712
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302713 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2714 if (err >= 0) {
2715 strlcpy(out->profile, value, sizeof(out->profile));
2716 ALOGV("updating stream profile with value '%s'", out->profile);
2717 lock_output_stream(out);
2718 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2719 &adev->streams_output_cfg_list,
2720 out->devices, out->flags, out->format,
2721 out->sample_rate, out->bit_width,
2722 out->channel_mask, out->profile,
2723 &out->app_type_cfg);
2724 pthread_mutex_unlock(&out->lock);
2725 }
2726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302728error:
Eric Laurent994a6932013-07-17 11:51:42 -07002729 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 return ret;
2731}
2732
2733static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2734{
2735 struct stream_out *out = (struct stream_out *)stream;
2736 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002737 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 char value[256];
2739 struct str_parms *reply = str_parms_create();
2740 size_t i, j;
2741 int ret;
2742 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002743
2744 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002745 if (reply) {
2746 str_parms_destroy(reply);
2747 }
2748 if (query) {
2749 str_parms_destroy(query);
2750 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002751 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2752 return NULL;
2753 }
2754
Eric Laurent994a6932013-07-17 11:51:42 -07002755 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2757 if (ret >= 0) {
2758 value[0] = '\0';
2759 i = 0;
2760 while (out->supported_channel_masks[i] != 0) {
2761 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2762 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2763 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002764 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002766 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 first = false;
2768 break;
2769 }
2770 }
2771 i++;
2772 }
2773 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2774 str = str_parms_to_str(reply);
2775 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002776 voice_extn_out_get_parameters(out, query, reply);
2777 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002778 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002779 free(str);
2780 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002783
Alexy Joseph62142aa2015-11-16 15:10:34 -08002784
2785 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2786 if (ret >= 0) {
2787 value[0] = '\0';
2788 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2789 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302790 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002791 } else {
2792 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302793 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002794 }
2795 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002796 if (str)
2797 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002798 str = str_parms_to_str(reply);
2799 }
2800
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002801 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2802 if (ret >= 0) {
2803 value[0] = '\0';
2804 i = 0;
2805 first = true;
2806 while (out->supported_formats[i] != 0) {
2807 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2808 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2809 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002810 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002811 }
2812 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2813 first = false;
2814 break;
2815 }
2816 }
2817 i++;
2818 }
2819 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002820 if (str)
2821 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002822 str = str_parms_to_str(reply);
2823 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002824
2825 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2826 if (ret >= 0) {
2827 value[0] = '\0';
2828 i = 0;
2829 first = true;
2830 while (out->supported_sample_rates[i] != 0) {
2831 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2832 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2833 if (!first) {
2834 strlcat(value, "|", sizeof(value));
2835 }
2836 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2837 first = false;
2838 break;
2839 }
2840 }
2841 i++;
2842 }
2843 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2844 if (str)
2845 free(str);
2846 str = str_parms_to_str(reply);
2847 }
2848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 str_parms_destroy(query);
2850 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002851 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 return str;
2853}
2854
2855static uint32_t out_get_latency(const struct audio_stream_out *stream)
2856{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002857 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002859 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860
Alexy Josephaa54c872014-12-03 02:46:47 -08002861 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002862 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002863 } else if (out->realtime) {
2864 // since the buffer won't be filled up faster than realtime,
2865 // return a smaller number
2866 if (out->config.rate)
2867 period_ms = (out->af_period_multiplier * out->config.period_size *
2868 1000) / (out->config.rate);
2869 else
2870 period_ms = 0;
2871 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002872 } else {
2873 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002875 }
2876
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302877 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002878 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879}
2880
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302881static float AmpToDb(float amplification)
2882{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302883 float db = DSD_VOLUME_MIN_DB;
2884 if (amplification > 0) {
2885 db = 20 * log10(amplification);
2886 if(db < DSD_VOLUME_MIN_DB)
2887 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302888 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302889 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302890}
2891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892static int out_set_volume(struct audio_stream_out *stream, float left,
2893 float right)
2894{
Eric Laurenta9024de2013-04-04 09:19:12 -07002895 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 int volume[2];
2897
Eric Laurenta9024de2013-04-04 09:19:12 -07002898 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2899 /* only take left channel into account: the API is for stereo anyway */
2900 out->muted = (left == 0.0f);
2901 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002902 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302903 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002904 /*
2905 * Set mute or umute on HDMI passthrough stream.
2906 * Only take left channel into account.
2907 * Mute is 0 and unmute 1
2908 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302909 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302910 } else if (out->format == AUDIO_FORMAT_DSD){
2911 char mixer_ctl_name[128] = "DSD Volume";
2912 struct audio_device *adev = out->dev;
2913 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2914
2915 if (!ctl) {
2916 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2917 __func__, mixer_ctl_name);
2918 return -EINVAL;
2919 }
2920 volume[0] = (int)(AmpToDb(left));
2921 volume[1] = (int)(AmpToDb(right));
2922 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2923 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002924 } else {
2925 char mixer_ctl_name[128];
2926 struct audio_device *adev = out->dev;
2927 struct mixer_ctl *ctl;
2928 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002929 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002931 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2932 "Compress Playback %d Volume", pcm_device_id);
2933 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2934 if (!ctl) {
2935 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2936 __func__, mixer_ctl_name);
2937 return -EINVAL;
2938 }
2939 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2940 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2941 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2942 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002944 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 return -ENOSYS;
2947}
2948
2949static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2950 size_t bytes)
2951{
2952 struct stream_out *out = (struct stream_out *)stream;
2953 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302954 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002955 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002957 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302958
Naresh Tanniru80659832014-06-04 18:17:56 +05302959 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002960
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302961 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302962 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302963 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2964 pthread_mutex_unlock(&out->lock);
2965 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302966 } else {
2967 /* increase written size during SSR to avoid mismatch
2968 * with the written frames count in AF
2969 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002970 // bytes per frame
2971 size_t bpf = audio_bytes_per_sample(out->format) *
2972 audio_channel_count_from_out_mask(out->channel_mask);
2973 if (bpf != 0)
2974 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302975 ALOGD(" %s: sound card is not active/SSR state", __func__);
2976 ret= -EIO;
2977 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302978 }
2979 }
2980
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302981 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302982 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2983 if (audio_bytes_per_sample(out->format) != 0)
2984 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2985 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302986 goto exit;
2987 }
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002990 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002991 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2993 ret = voice_extn_compress_voip_start_output_stream(out);
2994 else
2995 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002996 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002999 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 goto exit;
3001 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003002
3003 if (last_known_cal_step != -1) {
3004 ALOGD("%s: retry previous failed cal level set", __func__);
3005 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Ashish Jain81eb2a82015-05-13 10:52:34 +05303009 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003010 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303011 adev->is_channel_status_set = true;
3012 }
3013
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003014 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003015 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003016 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003017 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003018 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3019 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303020 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3021 ALOGD("copl(%p):send next track params in gapless", out);
3022 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3023 out->send_next_track_params = false;
3024 out->is_compr_metadata_avail = false;
3025 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003026 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303027 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303028 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003029
Ashish Jain83a6cc22016-06-28 14:34:17 +05303030 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303031 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303032 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303033 pthread_mutex_unlock(&out->lock);
3034 return -EINVAL;
3035 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303036 audio_format_t dst_format = out->hal_op_format;
3037 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303038
3039 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3040 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3041
Ashish Jain83a6cc22016-06-28 14:34:17 +05303042 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303043 dst_format,
3044 buffer,
3045 src_format,
3046 frames);
3047
Ashish Jain83a6cc22016-06-28 14:34:17 +05303048 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303049 bytes_to_write);
3050
3051 /*Convert written bytes in audio flinger format*/
3052 if (ret > 0)
3053 ret = ((ret * format_to_bitwidth_table[out->format]) /
3054 format_to_bitwidth_table[dst_format]);
3055 }
3056 } else
3057 ret = compress_write(out->compr, buffer, bytes);
3058
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303059 if (ret < 0)
3060 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303061 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303062 /*msg to cb thread only if non blocking write is enabled*/
3063 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303064 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303066 } else if (-ENETRESET == ret) {
3067 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3068 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3069 pthread_mutex_unlock(&out->lock);
3070 out_standby(&out->stream.common);
3071 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 }
Ashish Jain5106d362016-05-11 19:23:33 +05303073 if ( ret == (ssize_t)bytes && !out->non_blocking)
3074 out->written += bytes;
3075
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303076 /* Call compr start only when non-zero bytes of data is there to be rendered */
3077 if (!out->playback_started && ret > 0) {
3078 int status = compress_start(out->compr);
3079 if (status < 0) {
3080 ret = status;
3081 ALOGE("%s: compr start failed with err %d", __func__, errno);
3082 goto exit;
3083 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003084 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 out->playback_started = 1;
3086 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003087
3088 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3089 popcount(out->channel_mask),
3090 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 }
3092 pthread_mutex_unlock(&out->lock);
3093 return ret;
3094 } else {
3095 if (out->pcm) {
3096 if (out->muted)
3097 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003098
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303099 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003100
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003101 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003102
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003103 if (out->config.rate)
3104 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3105 out->config.rate;
3106
3107 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3108
3109 request_out_focus(out, ns);
3110
3111 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003112 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003113 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303114 out->convert_buffer != NULL) {
3115
3116 memcpy_by_audio_format(out->convert_buffer,
3117 out->hal_op_format,
3118 buffer,
3119 out->hal_ip_format,
3120 out->config.period_size * out->config.channels);
3121
3122 ret = pcm_write(out->pcm, out->convert_buffer,
3123 (out->config.period_size *
3124 out->config.channels *
3125 format_to_bitwidth_table[out->hal_op_format]));
3126 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003127 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303128 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003129
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003130 release_out_focus(out);
3131
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303132 if (ret < 0)
3133 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303134 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3135 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3136 else
3137 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 }
3140
3141exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303142 /* ToDo: There may be a corner case when SSR happens back to back during
3143 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303146 }
3147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 pthread_mutex_unlock(&out->lock);
3149
3150 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003151 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003152 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303153 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303154 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303155 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303156 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303157 out->standby = true;
3158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303160 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3161 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3162 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 }
3164 return bytes;
3165}
3166
3167static int out_get_render_position(const struct audio_stream_out *stream,
3168 uint32_t *dsp_frames)
3169{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303171 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003172
3173 if (dsp_frames == NULL)
3174 return -EINVAL;
3175
3176 *dsp_frames = 0;
3177 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003178 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303179
3180 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3181 * this operation and adev_close_output_stream(where out gets reset).
3182 */
3183 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3184 *dsp_frames = get_actual_pcm_frames_rendered(out);
3185 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3186 return 0;
3187 }
3188
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003189 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303190 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303191 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303193 if (ret < 0)
3194 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003195 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303196 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 }
3198 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303199 if (-ENETRESET == ret) {
3200 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3201 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3202 return -EINVAL;
3203 } else if(ret < 0) {
3204 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3205 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303206 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3207 /*
3208 * Handle corner case where compress session is closed during SSR
3209 * and timestamp is queried
3210 */
3211 ALOGE(" ERROR: sound card not active, return error");
3212 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303213 } else {
3214 return 0;
3215 }
Zhou Song32a556e2015-05-05 10:46:56 +08003216 } else if (audio_is_linear_pcm(out->format)) {
3217 *dsp_frames = out->written;
3218 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219 } else
3220 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221}
3222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003223static int out_add_audio_effect(const struct audio_stream *stream __unused,
3224 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225{
3226 return 0;
3227}
3228
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003229static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3230 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231{
3232 return 0;
3233}
3234
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003235static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3236 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237{
3238 return -EINVAL;
3239}
3240
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003241static int out_get_presentation_position(const struct audio_stream_out *stream,
3242 uint64_t *frames, struct timespec *timestamp)
3243{
3244 struct stream_out *out = (struct stream_out *)stream;
3245 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003246 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003247
Ashish Jain5106d362016-05-11 19:23:33 +05303248 /* below piece of code is not guarded against any lock because audioFliner serializes
3249 * this operation and adev_close_output_stream( where out gets reset).
3250 */
3251 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3252 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3253 *frames = get_actual_pcm_frames_rendered(out);
3254 /* this is the best we can do */
3255 clock_gettime(CLOCK_MONOTONIC, timestamp);
3256 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3257 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3258 return 0;
3259 }
3260
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003261 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003262
Ashish Jain5106d362016-05-11 19:23:33 +05303263 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3264 ret = compress_get_tstamp(out->compr, &dsp_frames,
3265 &out->sample_rate);
3266 ALOGVV("%s rendered frames %ld sample_rate %d",
3267 __func__, dsp_frames, out->sample_rate);
3268 *frames = dsp_frames;
3269 if (ret < 0)
3270 ret = -errno;
3271 if (-ENETRESET == ret) {
3272 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3273 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3274 ret = -EINVAL;
3275 } else
3276 ret = 0;
3277 /* this is the best we can do */
3278 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003279 } else {
3280 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003281 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003282 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3283 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003284 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003285 // This adjustment accounts for buffering after app processor.
3286 // It is based on estimated DSP latency per use case, rather than exact.
3287 signed_frames -=
3288 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3289
Eric Laurent949a0892013-09-20 09:20:13 -07003290 // It would be unusual for this value to be negative, but check just in case ...
3291 if (signed_frames >= 0) {
3292 *frames = signed_frames;
3293 ret = 0;
3294 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003295 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303296 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3297 *frames = out->written;
3298 clock_gettime(CLOCK_MONOTONIC, timestamp);
3299 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003300 }
3301 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003302 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003303 return ret;
3304}
3305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306static int out_set_callback(struct audio_stream_out *stream,
3307 stream_callback_t callback, void *cookie)
3308{
3309 struct stream_out *out = (struct stream_out *)stream;
3310
3311 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003312 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003313 out->offload_callback = callback;
3314 out->offload_cookie = cookie;
3315 pthread_mutex_unlock(&out->lock);
3316 return 0;
3317}
3318
3319static int out_pause(struct audio_stream_out* stream)
3320{
3321 struct stream_out *out = (struct stream_out *)stream;
3322 int status = -ENOSYS;
3323 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003324 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003325 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003326 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303328 struct audio_device *adev = out->dev;
3329 int snd_scard_state = get_snd_card_state(adev);
3330
3331 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3332 status = compress_pause(out->compr);
3333
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003335
Mingming Yin21854652016-04-13 11:54:02 -07003336 if (audio_extn_passthru_is_active()) {
3337 ALOGV("offload use case, pause passthru");
3338 audio_extn_passthru_on_pause(out);
3339 }
3340
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303341 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003342 audio_extn_dts_notify_playback_state(out->usecase, 0,
3343 out->sample_rate, popcount(out->channel_mask),
3344 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003345 }
3346 pthread_mutex_unlock(&out->lock);
3347 }
3348 return status;
3349}
3350
3351static int out_resume(struct audio_stream_out* stream)
3352{
3353 struct stream_out *out = (struct stream_out *)stream;
3354 int status = -ENOSYS;
3355 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003356 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003357 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003359 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303361 struct audio_device *adev = out->dev;
3362 int snd_scard_state = get_snd_card_state(adev);
3363
Mingming Yin21854652016-04-13 11:54:02 -07003364 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3365 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3366 pthread_mutex_lock(&out->dev->lock);
3367 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003368 pthread_mutex_unlock(&out->dev->lock);
3369 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303370 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003371 }
3372 if (!status) {
3373 out->offload_state = OFFLOAD_STATE_PLAYING;
3374 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303375 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003376 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3377 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 }
3379 pthread_mutex_unlock(&out->lock);
3380 }
3381 return status;
3382}
3383
3384static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3385{
3386 struct stream_out *out = (struct stream_out *)stream;
3387 int status = -ENOSYS;
3388 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003389 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003390 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003391 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3392 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3393 else
3394 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3395 pthread_mutex_unlock(&out->lock);
3396 }
3397 return status;
3398}
3399
3400static int out_flush(struct audio_stream_out* stream)
3401{
3402 struct stream_out *out = (struct stream_out *)stream;
3403 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003404 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003405 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003406 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003407 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3408 stop_compressed_output_l(out);
3409 out->written = 0;
3410 } else {
3411 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3412 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003414 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 return 0;
3416 }
3417 return -ENOSYS;
3418}
3419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420/** audio_stream_in implementation **/
3421static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3422{
3423 struct stream_in *in = (struct stream_in *)stream;
3424
3425 return in->config.rate;
3426}
3427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003428static int in_set_sample_rate(struct audio_stream *stream __unused,
3429 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430{
3431 return -ENOSYS;
3432}
3433
3434static size_t in_get_buffer_size(const struct audio_stream *stream)
3435{
3436 struct stream_in *in = (struct stream_in *)stream;
3437
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003438 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3439 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003440 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3441 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303442 else if(audio_extn_cin_attached_usecase(in->usecase))
3443 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003444
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003445 return in->config.period_size * in->af_period_multiplier *
3446 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447}
3448
3449static uint32_t in_get_channels(const struct audio_stream *stream)
3450{
3451 struct stream_in *in = (struct stream_in *)stream;
3452
3453 return in->channel_mask;
3454}
3455
3456static audio_format_t in_get_format(const struct audio_stream *stream)
3457{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003458 struct stream_in *in = (struct stream_in *)stream;
3459
3460 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461}
3462
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003463static int in_set_format(struct audio_stream *stream __unused,
3464 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465{
3466 return -ENOSYS;
3467}
3468
3469static int in_standby(struct audio_stream *stream)
3470{
3471 struct stream_in *in = (struct stream_in *)stream;
3472 struct audio_device *adev = in->dev;
3473 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303474 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3475 stream, in->usecase, use_case_table[in->usecase]);
3476
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003477 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003478 if (!in->standby && in->is_st_session) {
3479 ALOGD("%s: sound trigger pcm stop lab", __func__);
3480 audio_extn_sound_trigger_stop_lab(in);
3481 in->standby = 1;
3482 }
3483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003485 if (adev->adm_deregister_stream)
3486 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3487
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003488 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003490 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3491 voice_extn_compress_voip_close_input_stream(stream);
3492 ALOGD("VOIP input entered standby");
3493 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303494 if (audio_extn_cin_attached_usecase(in->usecase))
3495 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003496 if (in->pcm) {
3497 pcm_close(in->pcm);
3498 in->pcm = NULL;
3499 }
3500 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003501 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003502 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 }
3504 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003505 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 return status;
3507}
3508
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003509static int in_dump(const struct audio_stream *stream __unused,
3510 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511{
3512 return 0;
3513}
3514
3515static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3516{
3517 struct stream_in *in = (struct stream_in *)stream;
3518 struct audio_device *adev = in->dev;
3519 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003521 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303523 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 parms = str_parms_create_str(kvpairs);
3525
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303526 if (!parms)
3527 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003528 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003529 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003530
3531 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3532 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 val = atoi(value);
3534 /* no audio source uses val == 0 */
3535 if ((in->source != val) && (val != 0)) {
3536 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003537 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3538 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3539 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003540 (in->config.rate == 8000 || in->config.rate == 16000 ||
3541 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003542 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003543 err = voice_extn_compress_voip_open_input_stream(in);
3544 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003545 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003546 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003547 }
3548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 }
3550 }
3551
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003552 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3553 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003555 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 in->device = val;
3557 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003558 if (!in->standby && !in->is_st_session) {
3559 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003560 if (adev->adm_on_routing_change)
3561 adev->adm_on_routing_change(adev->adm_data,
3562 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003563 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 }
3566 }
3567
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303568 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3569 if (err >= 0) {
3570 strlcpy(in->profile, value, sizeof(in->profile));
3571 ALOGV("updating stream profile with value '%s'", in->profile);
3572 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3573 &adev->streams_input_cfg_list,
3574 in->device, in->flags, in->format,
3575 in->sample_rate, in->bit_width,
3576 in->profile, &in->app_type_cfg);
3577 }
3578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003580 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
3582 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303583error:
Eric Laurent994a6932013-07-17 11:51:42 -07003584 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 return ret;
3586}
3587
3588static char* in_get_parameters(const struct audio_stream *stream,
3589 const char *keys)
3590{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003591 struct stream_in *in = (struct stream_in *)stream;
3592 struct str_parms *query = str_parms_create_str(keys);
3593 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003594 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003595
3596 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003597 if (reply) {
3598 str_parms_destroy(reply);
3599 }
3600 if (query) {
3601 str_parms_destroy(query);
3602 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003603 ALOGE("in_get_parameters: failed to create query or reply");
3604 return NULL;
3605 }
3606
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003607 ALOGV("%s: enter: keys - %s", __func__, keys);
3608
3609 voice_extn_in_get_parameters(in, query, reply);
3610
3611 str = str_parms_to_str(reply);
3612 str_parms_destroy(query);
3613 str_parms_destroy(reply);
3614
3615 ALOGV("%s: exit: returns - %s", __func__, str);
3616 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617}
3618
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003619static int in_set_gain(struct audio_stream_in *stream __unused,
3620 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621{
3622 return 0;
3623}
3624
3625static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3626 size_t bytes)
3627{
3628 struct stream_in *in = (struct stream_in *)stream;
3629 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303630 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303631 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303632 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003634 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303635
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003636 if (in->is_st_session) {
3637 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3638 /* Read from sound trigger HAL */
3639 audio_extn_sound_trigger_read(in, buffer, bytes);
3640 pthread_mutex_unlock(&in->lock);
3641 return bytes;
3642 }
3643
Ashish Jainbbce4322016-02-16 13:25:27 +05303644 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003645 ALOGD(" %s: sound card is not active/SSR state", __func__);
3646 ret= -EIO;;
3647 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303648 }
3649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003651 pthread_mutex_lock(&adev->lock);
3652 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3653 ret = voice_extn_compress_voip_start_input_stream(in);
3654 else
3655 ret = start_input_stream(in);
3656 pthread_mutex_unlock(&adev->lock);
3657 if (ret != 0) {
3658 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 }
3660 in->standby = 0;
3661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003663 // what's the duration requested by the client?
3664 long ns = 0;
3665
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303666 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003667 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3668 in->config.rate;
3669
3670 request_in_focus(in, ns);
3671 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003672
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303673 if (audio_extn_cin_attached_usecase(in->usecase)) {
3674 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3675 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303676 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003677 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303678 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003679 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003680 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003681 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303682 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003683 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303684 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3685 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3686 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3687 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303688 ret = -EINVAL;
3689 goto exit;
3690 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303691 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303692 ret = -errno;
3693 }
3694 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303695 /* bytes read is always set to bytes for non compress usecases */
3696 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 }
3698
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003699 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 /*
3702 * Instead of writing zeroes here, we could trust the hardware
3703 * to always provide zeroes when muted.
3704 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303705 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3706 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 memset(buffer, 0, bytes);
3708
3709exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303710 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303711 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003712 if (-ENETRESET == ret)
3713 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 pthread_mutex_unlock(&in->lock);
3716
3717 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303718 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303719 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303720 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303721 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303722 in->standby = true;
3723 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303724 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003726 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303727 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303728 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303730 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731}
3732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003733static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734{
3735 return 0;
3736}
3737
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003738static int add_remove_audio_effect(const struct audio_stream *stream,
3739 effect_handle_t effect,
3740 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003742 struct stream_in *in = (struct stream_in *)stream;
3743 int status = 0;
3744 effect_descriptor_t desc;
3745
3746 status = (*effect)->get_descriptor(effect, &desc);
3747 if (status != 0)
3748 return status;
3749
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003750 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003751 pthread_mutex_lock(&in->dev->lock);
3752 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3753 in->enable_aec != enable &&
3754 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3755 in->enable_aec = enable;
3756 if (!in->standby)
3757 select_devices(in->dev, in->usecase);
3758 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003759 if (in->enable_ns != enable &&
3760 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3761 in->enable_ns = enable;
3762 if (!in->standby)
3763 select_devices(in->dev, in->usecase);
3764 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003765 pthread_mutex_unlock(&in->dev->lock);
3766 pthread_mutex_unlock(&in->lock);
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 return 0;
3769}
3770
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003771static int in_add_audio_effect(const struct audio_stream *stream,
3772 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773{
Eric Laurent994a6932013-07-17 11:51:42 -07003774 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003775 return add_remove_audio_effect(stream, effect, true);
3776}
3777
3778static int in_remove_audio_effect(const struct audio_stream *stream,
3779 effect_handle_t effect)
3780{
Eric Laurent994a6932013-07-17 11:51:42 -07003781 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003782 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783}
3784
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303785int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786 audio_io_handle_t handle,
3787 audio_devices_t devices,
3788 audio_output_flags_t flags,
3789 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003790 struct audio_stream_out **stream_out,
3791 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792{
3793 struct audio_device *adev = (struct audio_device *)dev;
3794 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303795 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003796 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303799
3800 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3801 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003802 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303803 return -EINVAL;
3804 }
3805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3807
Mingming Yin3a941d42016-02-17 18:08:05 -08003808 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3809 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303810 devices, flags, &out->stream);
3811
3812
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003813 if (!out) {
3814 return -ENOMEM;
3815 }
3816
Haynes Mathew George204045b2015-02-25 20:32:03 -08003817 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003818 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003819 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 if (devices == AUDIO_DEVICE_NONE)
3822 devices = AUDIO_DEVICE_OUT_SPEAKER;
3823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 out->flags = flags;
3825 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003826 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003827 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003828 out->sample_rate = config->sample_rate;
3829 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3830 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003831 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003832 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003833 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303834 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835
Mingming Yin3a941d42016-02-17 18:08:05 -08003836 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3837 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3838 pthread_mutex_lock(&adev->lock);
3839 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3840 ret = read_hdmi_sink_caps(out);
3841 pthread_mutex_unlock(&adev->lock);
3842 if (ret != 0) {
3843 if (ret == -ENOSYS) {
3844 /* ignore and go with default */
3845 ret = 0;
3846 } else {
3847 ALOGE("error reading hdmi sink caps");
3848 goto error_open;
3849 }
3850 }
3851 }
3852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003854 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303855 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3856 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003857 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3858 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3859
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003860 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003861 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3862 /*
3863 * Do not handle stereo output in Multi-channel cases
3864 * Stereo case is handled in normal playback path
3865 */
3866 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3867 ret = AUDIO_CHANNEL_OUT_STEREO;
3868 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003869
3870 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3871 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003872 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003873 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003874 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003875
3876 if (config->sample_rate == 0)
3877 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3878 if (config->channel_mask == 0)
3879 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003880 if (config->format == 0)
3881 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003882
3883 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003884 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003885 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3887 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003889 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003891 } 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 -08003892 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003893 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003894 ret = voice_extn_compress_voip_open_output_stream(out);
3895 if (ret != 0) {
3896 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3897 __func__, ret);
3898 goto error_open;
3899 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003900 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3901 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3902
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003903 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3904 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3905 ALOGE("%s: Unsupported Offload information", __func__);
3906 ret = -EINVAL;
3907 goto error_open;
3908 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003909
Mingming Yin3a941d42016-02-17 18:08:05 -08003910 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003911 if(config->offload_info.format == 0)
3912 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003913 if (config->offload_info.sample_rate == 0)
3914 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003915 }
3916
Mingming Yin90310102013-11-13 16:57:00 -08003917 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303918 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003919 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003920 ret = -EINVAL;
3921 goto error_open;
3922 }
3923
3924 out->compr_config.codec = (struct snd_codec *)
3925 calloc(1, sizeof(struct snd_codec));
3926
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003927 if (!out->compr_config.codec) {
3928 ret = -ENOMEM;
3929 goto error_open;
3930 }
3931
vivek mehta0ea887a2015-08-26 14:01:20 -07003932 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303933 out->stream.pause = out_pause;
3934 out->stream.flush = out_flush;
3935 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003936 out->usecase = get_offload_usecase(adev, true);
3937 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003938 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003939 out->stream.set_callback = out_set_callback;
3940 out->stream.pause = out_pause;
3941 out->stream.resume = out_resume;
3942 out->stream.drain = out_drain;
3943 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003944 out->usecase = get_offload_usecase(adev, false);
3945 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003946 }
vivek mehta446c3962015-09-14 10:57:35 -07003947
3948 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003949 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3950 config->format == 0 && config->sample_rate == 0 &&
3951 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003952 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003953 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3954 } else {
3955 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3956 ret = -EEXIST;
3957 goto error_open;
3958 }
vivek mehta446c3962015-09-14 10:57:35 -07003959 }
3960
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003961 if (config->offload_info.channel_mask)
3962 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003963 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003965 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003966 } else {
3967 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3968 ret = -EINVAL;
3969 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003970 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003971
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003972 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003973 out->sample_rate = config->offload_info.sample_rate;
3974
Mingming Yin3ee55c62014-08-04 14:23:35 -07003975 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303977 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3978 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3979 audio_extn_dolby_send_ddp_endp_params(adev);
3980 audio_extn_dolby_set_dmid(adev);
3981 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003984 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003985 out->compr_config.codec->bit_rate =
3986 config->offload_info.bit_rate;
3987 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303988 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003989 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303990 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003991 /*TODO: Do we need to change it for passthrough */
3992 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993
Manish Dewangana6fc5442015-08-24 20:30:31 +05303994 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3995 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05303996 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05303997 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05303998 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
3999 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304000
4001 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4002 AUDIO_FORMAT_PCM) {
4003
4004 /*Based on platform support, configure appropriate alsa format for corresponding
4005 *hal input format.
4006 */
4007 out->compr_config.codec->format = hal_format_to_alsa(
4008 config->offload_info.format);
4009
Ashish Jain83a6cc22016-06-28 14:34:17 +05304010 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304011 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304012 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304013
4014 /*for direct PCM playback populate bit_width based on selected alsa format as
4015 *hal input format and alsa format might differ based on platform support.
4016 */
4017 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304018 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304019
4020 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4021
4022 /* Check if alsa session is configured with the same format as HAL input format,
4023 * if not then derive correct fragment size needed to accomodate the
4024 * conversion of HAL input format to alsa format.
4025 */
4026 audio_extn_utils_update_direct_pcm_fragment_size(out);
4027
4028 /*if hal input and output fragment size is different this indicates HAL input format is
4029 *not same as the alsa format
4030 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304031 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304032 /*Allocate a buffer to convert input data to the alsa configured format.
4033 *size of convert buffer is equal to the size required to hold one fragment size
4034 *worth of pcm data, this is because flinger does not write more than fragment_size
4035 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304036 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4037 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304038 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4039 ret = -ENOMEM;
4040 goto error_open;
4041 }
4042 }
4043 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4044 out->compr_config.fragment_size =
4045 audio_extn_passthru_get_buffer_size(&config->offload_info);
4046 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4047 } else {
4048 out->compr_config.fragment_size =
4049 platform_get_compress_offload_buffer_size(&config->offload_info);
4050 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4051 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004052
Amit Shekhar6f461b12014-08-01 14:52:58 -07004053 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304054 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004055
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304056 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4057 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4058 }
4059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004060 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4061 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004062
Alexy Josephaa54c872014-12-03 02:46:47 -08004063
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004064 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304065 out->send_next_track_params = false;
4066 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004067 out->offload_state = OFFLOAD_STATE_IDLE;
4068 out->playback_started = 0;
4069
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004070 audio_extn_dts_create_state_notifier_node(out->usecase);
4071
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4073 __func__, config->offload_info.version,
4074 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304075
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304076 /* Check if DSD audio format is supported in codec
4077 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304078 */
4079
4080 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304081 (!platform_check_codec_dsd_support(adev->platform) ||
4082 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304083 ret = -EINVAL;
4084 goto error_open;
4085 }
4086
Ashish Jain5106d362016-05-11 19:23:33 +05304087 /* Disable gapless if any of the following is true
4088 * passthrough playback
4089 * AV playback
4090 * Direct PCM playback
4091 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304092 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304093 (config->format == AUDIO_FORMAT_DSD) ||
4094 config->offload_info.has_video ||
4095 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304096 check_and_set_gapless_mode(adev, false);
4097 } else
4098 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004099
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304100 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004101 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4102 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304103 if (config->format == AUDIO_FORMAT_DSD) {
4104 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4105 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4106 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004107
4108 create_offload_callback_thread(out);
4109
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004110 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304111 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004112 if (ret != 0) {
4113 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4114 __func__, ret);
4115 goto error_open;
4116 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004117 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4118 if (config->sample_rate == 0)
4119 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4120 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4121 config->sample_rate != 8000) {
4122 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4123 ret = -EINVAL;
4124 goto error_open;
4125 }
4126 out->sample_rate = config->sample_rate;
4127 out->config.rate = config->sample_rate;
4128 if (config->format == AUDIO_FORMAT_DEFAULT)
4129 config->format = AUDIO_FORMAT_PCM_16_BIT;
4130 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4131 config->format = AUDIO_FORMAT_PCM_16_BIT;
4132 ret = -EINVAL;
4133 goto error_open;
4134 }
4135 out->format = config->format;
4136 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4137 out->config = pcm_config_afe_proxy_playback;
4138 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004139 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304140 unsigned int channels = 0;
4141 /*Update config params to default if not set by the caller*/
4142 if (config->sample_rate == 0)
4143 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4144 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4145 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4146 if (config->format == AUDIO_FORMAT_DEFAULT)
4147 config->format = AUDIO_FORMAT_PCM_16_BIT;
4148
4149 channels = audio_channel_count_from_out_mask(out->channel_mask);
4150
Ashish Jain83a6cc22016-06-28 14:34:17 +05304151 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4152 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004153 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4154 out->flags);
4155 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304156 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4157 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4158 out->config = pcm_config_low_latency;
4159 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4160 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4161 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304162 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4163 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4164 if (out->config.period_size <= 0) {
4165 ALOGE("Invalid configuration period size is not valid");
4166 ret = -EINVAL;
4167 goto error_open;
4168 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304169 } else {
4170 /* primary path is the default path selected if no other outputs are available/suitable */
4171 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4172 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4173 }
4174 out->hal_ip_format = format = out->format;
4175 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4176 out->hal_op_format = pcm_format_to_hal(out->config.format);
4177 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4178 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004179 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304180 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304181 if (out->hal_ip_format != out->hal_op_format) {
4182 uint32_t buffer_size = out->config.period_size *
4183 format_to_bitwidth_table[out->hal_op_format] *
4184 out->config.channels;
4185 out->convert_buffer = calloc(1, buffer_size);
4186 if (out->convert_buffer == NULL){
4187 ALOGE("Allocation failed for convert buffer for size %d",
4188 out->compr_config.fragment_size);
4189 ret = -ENOMEM;
4190 goto error_open;
4191 }
4192 ALOGD("Convert buffer allocated of size %d", buffer_size);
4193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 }
4195
Ashish Jain83a6cc22016-06-28 14:34:17 +05304196 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4197 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4198
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004199 /* TODO remove this hardcoding and check why width is zero*/
4200 if (out->bit_width == 0)
4201 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304202 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004203 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304204 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304205 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304206 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004207 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4208 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4209 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004210 if(adev->primary_output == NULL)
4211 adev->primary_output = out;
4212 else {
4213 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004214 ret = -EEXIST;
4215 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004216 }
4217 }
4218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219 /* Check if this usecase is already existing */
4220 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004221 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4222 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004225 ret = -EEXIST;
4226 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227 }
4228 pthread_mutex_unlock(&adev->lock);
4229
4230 out->stream.common.get_sample_rate = out_get_sample_rate;
4231 out->stream.common.set_sample_rate = out_set_sample_rate;
4232 out->stream.common.get_buffer_size = out_get_buffer_size;
4233 out->stream.common.get_channels = out_get_channels;
4234 out->stream.common.get_format = out_get_format;
4235 out->stream.common.set_format = out_set_format;
4236 out->stream.common.standby = out_standby;
4237 out->stream.common.dump = out_dump;
4238 out->stream.common.set_parameters = out_set_parameters;
4239 out->stream.common.get_parameters = out_get_parameters;
4240 out->stream.common.add_audio_effect = out_add_audio_effect;
4241 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4242 out->stream.get_latency = out_get_latency;
4243 out->stream.set_volume = out_set_volume;
4244 out->stream.write = out_write;
4245 out->stream.get_render_position = out_get_render_position;
4246 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004247 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004249 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004251 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004252 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
4254 config->format = out->stream.common.get_format(&out->stream.common);
4255 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4256 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4257
4258 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304259 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004260 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004261
4262 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4263 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4264 popcount(out->channel_mask), out->playback_started);
4265
Eric Laurent994a6932013-07-17 11:51:42 -07004266 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004268
4269error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304270 if (out->convert_buffer)
4271 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004272 free(out);
4273 *stream_out = NULL;
4274 ALOGD("%s: exit: ret %d", __func__, ret);
4275 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276}
4277
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304278void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 struct audio_stream_out *stream)
4280{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004281 struct stream_out *out = (struct stream_out *)stream;
4282 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004283 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004284
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304285 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4286
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004287 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304288 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004289 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304290 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004291 if(ret != 0)
4292 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4293 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004294 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004295 out_standby(&stream->common);
4296
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004297 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004298 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004299 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004300 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004301 if (out->compr_config.codec != NULL)
4302 free(out->compr_config.codec);
4303 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004304
Ashish Jain83a6cc22016-06-28 14:34:17 +05304305 if (out->convert_buffer != NULL) {
4306 free(out->convert_buffer);
4307 out->convert_buffer = NULL;
4308 }
4309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004310 if (adev->voice_tx_output == out)
4311 adev->voice_tx_output = NULL;
4312
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004313 pthread_cond_destroy(&out->cond);
4314 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004316 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317}
4318
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004319static void close_compress_sessions(struct audio_device *adev)
4320{
Mingming Yin7b762e72015-03-04 13:47:32 -08004321 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304322 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004323 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004324 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304325
4326 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004327 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304328 if (is_offload_usecase(usecase->id)) {
4329 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004330 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4331 out = usecase->stream.out;
4332 pthread_mutex_unlock(&adev->lock);
4333 out_standby(&out->stream.common);
4334 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004335 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004336 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304337 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004338 }
4339 pthread_mutex_unlock(&adev->lock);
4340}
4341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4343{
4344 struct audio_device *adev = (struct audio_device *)dev;
4345 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004347 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004348 int ret;
4349 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004351 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304354 if (!parms)
4355 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004356 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4357 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304358 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304359 if (strstr(snd_card_status, "OFFLINE")) {
4360 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304361 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004362 //close compress sessions on OFFLINE status
4363 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304364 } else if (strstr(snd_card_status, "ONLINE")) {
4365 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304366 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004367 //send dts hpx license if enabled
4368 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304369 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304370 }
4371
4372 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004373 status = voice_set_parameters(adev, parms);
4374 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004375 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004377 status = platform_set_parameters(adev->platform, parms);
4378 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004379 goto done;
4380
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004381 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4382 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004383 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4385 adev->bluetooth_nrec = true;
4386 else
4387 adev->bluetooth_nrec = false;
4388 }
4389
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004390 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4391 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4393 adev->screen_off = false;
4394 else
4395 adev->screen_off = true;
4396 }
4397
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004398 ret = str_parms_get_int(parms, "rotation", &val);
4399 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004400 bool reverse_speakers = false;
4401 switch(val) {
4402 // FIXME: note that the code below assumes that the speakers are in the correct placement
4403 // relative to the user when the device is rotated 90deg from its default rotation. This
4404 // assumption is device-specific, not platform-specific like this code.
4405 case 270:
4406 reverse_speakers = true;
4407 break;
4408 case 0:
4409 case 90:
4410 case 180:
4411 break;
4412 default:
4413 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004414 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004415 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004416 if (status == 0) {
4417 if (adev->speaker_lr_swap != reverse_speakers) {
4418 adev->speaker_lr_swap = reverse_speakers;
4419 // only update the selected device if there is active pcm playback
4420 struct audio_usecase *usecase;
4421 struct listnode *node;
4422 list_for_each(node, &adev->usecase_list) {
4423 usecase = node_to_item(node, struct audio_usecase, list);
4424 if (usecase->type == PCM_PLAYBACK) {
4425 select_devices(adev, usecase->id);
4426 break;
4427 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004428 }
4429 }
4430 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004431 }
4432
Mingming Yin514a8bc2014-07-29 15:22:21 -07004433 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4434 if (ret >= 0) {
4435 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4436 adev->bt_wb_speech_enabled = true;
4437 else
4438 adev->bt_wb_speech_enabled = false;
4439 }
4440
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004441 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4442 if (ret >= 0) {
4443 val = atoi(value);
4444 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004445 ALOGV("cache new ext disp type and edid");
4446 ret = platform_get_ext_disp_type(adev->platform);
4447 if (ret < 0) {
4448 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004449 status = ret;
4450 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004451 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004452 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004453 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004454 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004455 /*
4456 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4457 * Per AudioPolicyManager, USB device is higher priority than WFD.
4458 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4459 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4460 * starting voice call on USB
4461 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004462 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4463 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004464 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4465 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004466 }
vivek mehta344576a2016-04-12 18:56:03 -07004467 ALOGV("detected USB connect .. disable proxy");
4468 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004469 }
4470 }
4471
4472 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4473 if (ret >= 0) {
4474 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004475 /*
4476 * The HDMI / Displayport disconnect handling has been moved to
4477 * audio extension to ensure that its parameters are not
4478 * invalidated prior to updating sysfs of the disconnect event
4479 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4480 */
4481 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004482 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004483 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4484 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304485 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4486 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004487 }
vivek mehta344576a2016-04-12 18:56:03 -07004488 ALOGV("detected USB disconnect .. enable proxy");
4489 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004490 }
4491 }
4492
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304493 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4494 if (ret >= 0) {
4495 struct audio_usecase *usecase;
4496 struct listnode *node;
4497 list_for_each(node, &adev->usecase_list) {
4498 usecase = node_to_item(node, struct audio_usecase, list);
4499 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004500 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304501 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304502 lock_output_stream(usecase->stream.out);
4503 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304504 //force device switch to re configure encoder
4505 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304506 audio_extn_a2dp_set_handoff_mode(false);
4507 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304508 break;
4509 }
4510 }
4511 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304512 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004513done:
4514 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004515 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304516error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004517 ALOGV("%s: exit with code(%d)", __func__, status);
4518 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004519}
4520
4521static char* adev_get_parameters(const struct audio_hw_device *dev,
4522 const char *keys)
4523{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004524 struct audio_device *adev = (struct audio_device *)dev;
4525 struct str_parms *reply = str_parms_create();
4526 struct str_parms *query = str_parms_create_str(keys);
4527 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304528 char value[256] = {0};
4529 int ret = 0;
4530
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004531 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004532 if (reply) {
4533 str_parms_destroy(reply);
4534 }
4535 if (query) {
4536 str_parms_destroy(query);
4537 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004538 ALOGE("adev_get_parameters: failed to create query or reply");
4539 return NULL;
4540 }
4541
Naresh Tannirud7205b62014-06-20 02:54:48 +05304542 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4543 sizeof(value));
4544 if (ret >=0) {
4545 int val = 1;
4546 pthread_mutex_lock(&adev->snd_card_status.lock);
4547 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4548 val = 0;
4549 pthread_mutex_unlock(&adev->snd_card_status.lock);
4550 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4551 goto exit;
4552 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004553
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004554 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004555 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004556 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004557 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304558 pthread_mutex_unlock(&adev->lock);
4559
Naresh Tannirud7205b62014-06-20 02:54:48 +05304560exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004561 str = str_parms_to_str(reply);
4562 str_parms_destroy(query);
4563 str_parms_destroy(reply);
4564
4565 ALOGV("%s: exit: returns - %s", __func__, str);
4566 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567}
4568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004569static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570{
4571 return 0;
4572}
4573
4574static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4575{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004576 int ret;
4577 struct audio_device *adev = (struct audio_device *)dev;
4578 pthread_mutex_lock(&adev->lock);
4579 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004580 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004581 pthread_mutex_unlock(&adev->lock);
4582 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583}
4584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004585static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4586 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587{
4588 return -ENOSYS;
4589}
4590
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004591static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4592 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593{
4594 return -ENOSYS;
4595}
4596
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004597static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4598 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599{
4600 return -ENOSYS;
4601}
4602
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004603static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4604 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605{
4606 return -ENOSYS;
4607}
4608
4609static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4610{
4611 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 pthread_mutex_lock(&adev->lock);
4614 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004615 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004617 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004618 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004619 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004620 adev->current_call_output = NULL;
4621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 }
4623 pthread_mutex_unlock(&adev->lock);
4624 return 0;
4625}
4626
4627static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4628{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004629 int ret;
4630
4631 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004632 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004633 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4634 pthread_mutex_unlock(&adev->lock);
4635
4636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637}
4638
4639static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4640{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004641 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 return 0;
4643}
4644
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004645static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 const struct audio_config *config)
4647{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004648 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004650 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4651 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652}
4653
4654static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004655 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 audio_devices_t devices,
4657 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004658 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304659 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004660 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004661 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662{
4663 struct audio_device *adev = (struct audio_device *)dev;
4664 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004665 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004666 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004667 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304668 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304671 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4672 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004673 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675
4676 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004677
4678 if (!in) {
4679 ALOGE("failed to allocate input stream");
4680 return -ENOMEM;
4681 }
4682
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304683 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304684 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4685 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004686 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004687 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 in->stream.common.get_sample_rate = in_get_sample_rate;
4690 in->stream.common.set_sample_rate = in_set_sample_rate;
4691 in->stream.common.get_buffer_size = in_get_buffer_size;
4692 in->stream.common.get_channels = in_get_channels;
4693 in->stream.common.get_format = in_get_format;
4694 in->stream.common.set_format = in_set_format;
4695 in->stream.common.standby = in_standby;
4696 in->stream.common.dump = in_dump;
4697 in->stream.common.set_parameters = in_set_parameters;
4698 in->stream.common.get_parameters = in_get_parameters;
4699 in->stream.common.add_audio_effect = in_add_audio_effect;
4700 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4701 in->stream.set_gain = in_set_gain;
4702 in->stream.read = in_read;
4703 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4704
4705 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004706 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 in->standby = 1;
4709 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004710 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004711 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304713 in->usecase = USECASE_AUDIO_RECORD;
4714 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4715 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4716 is_low_latency = true;
4717#if LOW_LATENCY_CAPTURE_USE_CASE
4718 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4719#endif
4720 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4721 }
4722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004723 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004724 if (in->realtime) {
4725 in->config = pcm_config_audio_capture_rt;
4726 in->sample_rate = in->config.rate;
4727 in->af_period_multiplier = af_period_multiplier;
4728 } else {
4729 in->config = pcm_config_audio_capture;
4730 in->config.rate = config->sample_rate;
4731 in->sample_rate = config->sample_rate;
4732 in->af_period_multiplier = 1;
4733 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304734 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004735
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304736 /* restrict 24 bit capture for unprocessed source only
4737 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4738 */
4739 if (config->format == AUDIO_FORMAT_DEFAULT) {
4740 config->format = AUDIO_FORMAT_PCM_16_BIT;
4741 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4742 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4743 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4744 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4745 bool ret_error = false;
4746 in->bit_width = 24;
4747 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4748 from HAL is 24_packed and 8_24
4749 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4750 24_packed return error indicating supported format is 24_packed
4751 *> In case of any other source requesting 24 bit or float return error
4752 indicating format supported is 16 bit only.
4753
4754 on error flinger will retry with supported format passed
4755 */
4756 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4757 (source != AUDIO_SOURCE_CAMCORDER)) {
4758 config->format = AUDIO_FORMAT_PCM_16_BIT;
4759 if (config->sample_rate > 48000)
4760 config->sample_rate = 48000;
4761 ret_error = true;
4762 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4763 in->config.format = PCM_FORMAT_S24_3LE;
4764 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4765 in->config.format = PCM_FORMAT_S24_LE;
4766 } else {
4767 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4768 ret_error = true;
4769 }
4770
4771 if (ret_error) {
4772 ret = -EINVAL;
4773 goto err_open;
4774 }
4775 }
4776
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304777 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304778 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4779 (adev->mode != AUDIO_MODE_IN_CALL)) {
4780 ret = -EINVAL;
4781 goto err_open;
4782 }
4783
4784 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4785 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004786 if (config->sample_rate == 0)
4787 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4788 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4789 config->sample_rate != 8000) {
4790 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4791 ret = -EINVAL;
4792 goto err_open;
4793 }
4794 if (config->format == AUDIO_FORMAT_DEFAULT)
4795 config->format = AUDIO_FORMAT_PCM_16_BIT;
4796 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4797 config->format = AUDIO_FORMAT_PCM_16_BIT;
4798 ret = -EINVAL;
4799 goto err_open;
4800 }
4801
4802 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4803 in->config = pcm_config_afe_proxy_record;
4804 in->config.channels = channel_count;
4805 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304806 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304807 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4808 in, config, &channel_mask_updated)) {
4809 if (channel_mask_updated == true) {
4810 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4811 __func__, config->channel_mask);
4812 ret = -EINVAL;
4813 goto err_open;
4814 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304815 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004816 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004817 audio_extn_compr_cap_format_supported(config->format) &&
4818 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004819 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304820 } else if (audio_extn_cin_applicable_stream(in)) {
4821 ret = audio_extn_cin_configure_input_stream(in);
4822 if (ret)
4823 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004824 } else {
4825 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004826 if (!in->realtime) {
4827 in->format = config->format;
4828 frame_size = audio_stream_in_frame_size(&in->stream);
4829 buffer_size = get_input_buffer_size(config->sample_rate,
4830 config->format,
4831 channel_count,
4832 is_low_latency);
4833 in->config.period_size = buffer_size / frame_size;
4834 }
4835
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004836 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004837 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004838 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004839 (in->config.rate == 8000 || in->config.rate == 16000 ||
4840 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004841 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4842 voice_extn_compress_voip_open_input_stream(in);
4843 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304846 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4847 &adev->streams_input_cfg_list,
4848 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304849 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304850
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004851 /* This stream could be for sound trigger lab,
4852 get sound trigger pcm if present */
4853 audio_extn_sound_trigger_check_and_get_session(in);
4854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004856 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004857 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858
4859err_open:
4860 free(in);
4861 *stream_in = NULL;
4862 return ret;
4863}
4864
4865static void adev_close_input_stream(struct audio_hw_device *dev,
4866 struct audio_stream_in *stream)
4867{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004868 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004869 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004870 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304871
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304872 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004873
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304874 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004875 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304876
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004877 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304878 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004879 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304880 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004881 if (ret != 0)
4882 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4883 __func__, ret);
4884 } else
4885 in_standby(&stream->common);
4886
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004887 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004888 audio_extn_ssr_deinit();
4889 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304891 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004892 audio_extn_compr_cap_format_supported(in->config.format))
4893 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304894
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304895 if (audio_extn_cin_attached_usecase(in->usecase))
4896 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004897
Mingming Yinfd7607b2016-01-22 12:48:44 -08004898 if (in->is_st_session) {
4899 ALOGV("%s: sound trigger pcm stop lab", __func__);
4900 audio_extn_sound_trigger_stop_lab(in);
4901 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004902 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 return;
4904}
4905
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004906static int adev_dump(const audio_hw_device_t *device __unused,
4907 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908{
4909 return 0;
4910}
4911
4912static int adev_close(hw_device_t *device)
4913{
4914 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004915
4916 if (!adev)
4917 return 0;
4918
4919 pthread_mutex_lock(&adev_init_lock);
4920
4921 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004922 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004923 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304924 audio_extn_utils_release_streams_cfg_lists(
4925 &adev->streams_output_cfg_list,
4926 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304927 if (audio_extn_qaf_is_enabled())
4928 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004929 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004930 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004931 free(adev->snd_dev_ref_cnt);
4932 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004933 if (adev->adm_deinit)
4934 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304935 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004936 free(device);
4937 adev = NULL;
4938 }
4939 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004941 return 0;
4942}
4943
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004944/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4945 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4946 * just that it _might_ work.
4947 */
4948static int period_size_is_plausible_for_low_latency(int period_size)
4949{
4950 switch (period_size) {
4951 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004952 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004953 case 240:
4954 case 320:
4955 case 480:
4956 return 1;
4957 default:
4958 return 0;
4959 }
4960}
4961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004962static int adev_open(const hw_module_t *module, const char *name,
4963 hw_device_t **device)
4964{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304965 int ret;
4966
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004967 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4969
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004970 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004971 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004972 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004973 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004974 ALOGD("%s: returning existing instance of adev", __func__);
4975 ALOGD("%s: exit", __func__);
4976 pthread_mutex_unlock(&adev_init_lock);
4977 return 0;
4978 }
4979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 adev = calloc(1, sizeof(struct audio_device));
4981
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004982 if (!adev) {
4983 pthread_mutex_unlock(&adev_init_lock);
4984 return -ENOMEM;
4985 }
4986
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004987 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4990 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4991 adev->device.common.module = (struct hw_module_t *)module;
4992 adev->device.common.close = adev_close;
4993
4994 adev->device.init_check = adev_init_check;
4995 adev->device.set_voice_volume = adev_set_voice_volume;
4996 adev->device.set_master_volume = adev_set_master_volume;
4997 adev->device.get_master_volume = adev_get_master_volume;
4998 adev->device.set_master_mute = adev_set_master_mute;
4999 adev->device.get_master_mute = adev_get_master_mute;
5000 adev->device.set_mode = adev_set_mode;
5001 adev->device.set_mic_mute = adev_set_mic_mute;
5002 adev->device.get_mic_mute = adev_get_mic_mute;
5003 adev->device.set_parameters = adev_set_parameters;
5004 adev->device.get_parameters = adev_get_parameters;
5005 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5006 adev->device.open_output_stream = adev_open_output_stream;
5007 adev->device.close_output_stream = adev_close_output_stream;
5008 adev->device.open_input_stream = adev_open_input_stream;
5009 adev->device.close_input_stream = adev_close_input_stream;
5010 adev->device.dump = adev_dump;
5011
5012 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005014 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005015 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005018 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005019 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005020 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005021 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005022 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005023 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005024 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005025 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305026 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305027 adev->perf_lock_opts[0] = 0x101;
5028 adev->perf_lock_opts[1] = 0x20E;
5029 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305030
5031 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5032 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005034 adev->platform = platform_init(adev);
5035 if (!adev->platform) {
5036 free(adev->snd_dev_ref_cnt);
5037 free(adev);
5038 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5039 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005040 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305041 pthread_mutex_destroy(&adev->lock);
5042 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005043 return -EINVAL;
5044 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005045
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305046 if (audio_extn_qaf_is_enabled()) {
5047 ret = audio_extn_qaf_init(adev);
5048 if (ret < 0) {
5049 free(adev);
5050 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5051 *device = NULL;
5052 pthread_mutex_unlock(&adev_init_lock);
5053 pthread_mutex_destroy(&adev->lock);
5054 return ret;
5055 }
5056
5057 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5058 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5059 }
5060
Naresh Tanniru4c630392014-05-12 01:05:52 +05305061 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5062
Eric Laurentc4aef752013-09-12 17:45:53 -07005063 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5064 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5065 if (adev->visualizer_lib == NULL) {
5066 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5067 } else {
5068 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5069 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005070 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005071 "visualizer_hal_start_output");
5072 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005073 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005074 "visualizer_hal_stop_output");
5075 }
5076 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305077 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005078 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005079 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005080 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005081
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005082 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5083 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5084 if (adev->offload_effects_lib == NULL) {
5085 ALOGE("%s: DLOPEN failed for %s", __func__,
5086 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5087 } else {
5088 ALOGV("%s: DLOPEN successful for %s", __func__,
5089 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5090 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305091 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005092 "offload_effects_bundle_hal_start_output");
5093 adev->offload_effects_stop_output =
5094 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5095 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005096 adev->offload_effects_set_hpx_state =
5097 (int (*)(bool))dlsym(adev->offload_effects_lib,
5098 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305099 adev->offload_effects_get_parameters =
5100 (void (*)(struct str_parms *, struct str_parms *))
5101 dlsym(adev->offload_effects_lib,
5102 "offload_effects_bundle_get_parameters");
5103 adev->offload_effects_set_parameters =
5104 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5105 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005106 }
5107 }
5108
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005109 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5110 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5111 if (adev->adm_lib == NULL) {
5112 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5113 } else {
5114 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5115 adev->adm_init = (adm_init_t)
5116 dlsym(adev->adm_lib, "adm_init");
5117 adev->adm_deinit = (adm_deinit_t)
5118 dlsym(adev->adm_lib, "adm_deinit");
5119 adev->adm_register_input_stream = (adm_register_input_stream_t)
5120 dlsym(adev->adm_lib, "adm_register_input_stream");
5121 adev->adm_register_output_stream = (adm_register_output_stream_t)
5122 dlsym(adev->adm_lib, "adm_register_output_stream");
5123 adev->adm_deregister_stream = (adm_deregister_stream_t)
5124 dlsym(adev->adm_lib, "adm_deregister_stream");
5125 adev->adm_request_focus = (adm_request_focus_t)
5126 dlsym(adev->adm_lib, "adm_request_focus");
5127 adev->adm_abandon_focus = (adm_abandon_focus_t)
5128 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005129 adev->adm_set_config = (adm_set_config_t)
5130 dlsym(adev->adm_lib, "adm_set_config");
5131 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5132 dlsym(adev->adm_lib, "adm_request_focus_v2");
5133 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5134 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5135 adev->adm_on_routing_change = (adm_on_routing_change_t)
5136 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005137 }
5138 }
5139
Mingming Yin514a8bc2014-07-29 15:22:21 -07005140 adev->bt_wb_speech_enabled = false;
5141
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005142 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143 *device = &adev->device.common;
5144
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305145 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5146 &adev->streams_output_cfg_list,
5147 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005148
Kiran Kandi910e1862013-10-29 13:29:42 -07005149 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005150
5151 char value[PROPERTY_VALUE_MAX];
5152 int trial;
5153 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5154 trial = atoi(value);
5155 if (period_size_is_plausible_for_low_latency(trial)) {
5156 pcm_config_low_latency.period_size = trial;
5157 pcm_config_low_latency.start_threshold = trial / 4;
5158 pcm_config_low_latency.avail_min = trial / 4;
5159 configured_low_latency_capture_period_size = trial;
5160 }
5161 }
5162 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5163 trial = atoi(value);
5164 if (period_size_is_plausible_for_low_latency(trial)) {
5165 configured_low_latency_capture_period_size = trial;
5166 }
5167 }
5168
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005169 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5170 af_period_multiplier = atoi(value);
5171 if (af_period_multiplier < 0)
5172 af_period_multiplier = 2;
5173 else if (af_period_multiplier > 4)
5174 af_period_multiplier = 4;
5175
5176 ALOGV("new period_multiplier = %d", af_period_multiplier);
5177 }
5178
vivek mehta446c3962015-09-14 10:57:35 -07005179 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005180 pthread_mutex_unlock(&adev_init_lock);
5181
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005182 if (adev->adm_init)
5183 adev->adm_data = adev->adm_init();
5184
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305185 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305186 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005187 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005188 return 0;
5189}
5190
5191static struct hw_module_methods_t hal_module_methods = {
5192 .open = adev_open,
5193};
5194
5195struct audio_module HAL_MODULE_INFO_SYM = {
5196 .common = {
5197 .tag = HARDWARE_MODULE_TAG,
5198 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5199 .hal_api_version = HARDWARE_HAL_API_VERSION,
5200 .id = AUDIO_HARDWARE_MODULE_ID,
5201 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005202 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005203 .methods = &hal_module_methods,
5204 },
5205};