blob: 61e9b8994c8ff2ea7dc0cd7815777aa0e879f613 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530506 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
507 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530508 format == AUDIO_FORMAT_PCM_FLOAT ||
509 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700510 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530511 format == AUDIO_FORMAT_AC3 ||
512 format == AUDIO_FORMAT_E_AC3 ||
513 format == AUDIO_FORMAT_DTS ||
514 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800515 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530516 format == AUDIO_FORMAT_ALAC ||
517 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530518 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800520 format == AUDIO_FORMAT_WMA ||
521 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800522 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523
524 return false;
525}
526
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700527static inline bool is_mmap_usecase(audio_usecase_t uc_id)
528{
529 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
530 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
531}
532
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530533int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530534{
535 int snd_scard_state;
536
537 if (!adev)
538 return SND_CARD_STATE_OFFLINE;
539
540 pthread_mutex_lock(&adev->snd_card_status.lock);
541 snd_scard_state = adev->snd_card_status.state;
542 pthread_mutex_unlock(&adev->snd_card_status.lock);
543
544 return snd_scard_state;
545}
546
547static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
548{
549 if (!adev)
550 return -ENOSYS;
551
552 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700553 if (adev->snd_card_status.state != snd_scard_state) {
554 adev->snd_card_status.state = snd_scard_state;
555 platform_snd_card_update(adev->platform, snd_scard_state);
556 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530557 pthread_mutex_unlock(&adev->snd_card_status.lock);
558
559 return 0;
560}
561
Avinash Vaish71a8b972014-07-24 15:36:33 +0530562static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
563 struct audio_usecase *uc_info)
564{
565 struct listnode *node;
566 struct audio_usecase *usecase;
567
568 if (uc_info == NULL)
569 return -EINVAL;
570
571 /* Re-route all voice usecases on the shared backend other than the
572 specified usecase to new snd devices */
573 list_for_each(node, &adev->usecase_list) {
574 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800575 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530576 enable_audio_route(adev, usecase);
577 }
578 return 0;
579}
580
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530581static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530582{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530583 ALOGV("%s", __func__);
584 audio_route_apply_and_update_path(adev->audio_route,
585 "asrc-mode");
586 adev->asrc_mode_enabled = true;
587}
588
589static void disable_asrc_mode(struct audio_device *adev)
590{
591 ALOGV("%s", __func__);
592 audio_route_reset_and_update_path(adev->audio_route,
593 "asrc-mode");
594 adev->asrc_mode_enabled = false;
595}
596
597/*
598 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
599 * 44.1 or Native DSD backends are enabled for any of current use case.
600 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
601 * - Disable current mix path use case(Headphone backend) and re-enable it with
602 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
603 * e.g. Naitve DSD or Headphone 44.1 -> + 48
604 */
605static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
606{
607 ALOGV("%s snd device %d", __func__, snd_device);
608 int new_backend_idx = platform_get_backend_index(snd_device);
609
610 if (((new_backend_idx == HEADPHONE_BACKEND) ||
611 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
612 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
613 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530614 struct listnode *node = NULL;
615 struct audio_usecase *uc = NULL;
616 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530617 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618
619 list_for_each(node, &adev->usecase_list) {
620 uc = node_to_item(node, struct audio_usecase, list);
621 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530622 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530623 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
624
625 if((new_backend_idx == HEADPHONE_BACKEND) &&
626 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
627 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530628 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
629 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530630 enable_asrc_mode(adev);
631 break;
632 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
633 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
634 (usecase_backend_idx == HEADPHONE_BACKEND)) {
635 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
636 __func__);
637 disable_audio_route(adev, uc);
638 disable_snd_device(adev, uc->out_snd_device);
639 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
640 if (new_backend_idx == DSD_NATIVE_BACKEND)
641 audio_route_apply_and_update_path(adev->audio_route,
642 "hph-true-highquality-mode");
643 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
644 (curr_out->bit_width >= 24))
645 audio_route_apply_and_update_path(adev->audio_route,
646 "hph-highquality-mode");
647 enable_asrc_mode(adev);
648 enable_snd_device(adev, uc->out_snd_device);
649 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530650 break;
651 }
652 }
653 }
654 }
655}
656
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700657int pcm_ioctl(struct pcm *pcm, int request, ...)
658{
659 va_list ap;
660 void * arg;
661 int pcm_fd = *(int*)pcm;
662
663 va_start(ap, request);
664 arg = va_arg(ap, void *);
665 va_end(ap);
666
667 return ioctl(pcm_fd, request, arg);
668}
669
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700670int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700671 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700674 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800675
676 if (usecase == NULL)
677 return -EINVAL;
678
679 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
680
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800681 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800683 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800685
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800686#ifdef DS1_DOLBY_DAP_ENABLED
687 audio_extn_dolby_set_dmid(adev);
688 audio_extn_dolby_set_endpoint(adev);
689#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700690 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700691 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530692 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700693 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530694 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800695 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700696 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700697 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700698 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699 ALOGV("%s: exit", __func__);
700 return 0;
701}
702
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700703int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700704 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700707 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530709 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800710 return -EINVAL;
711
712 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 if (usecase->type == PCM_CAPTURE)
714 snd_device = usecase->in_snd_device;
715 else
716 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800717 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700718 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700719 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700720 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700721 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530722 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723 ALOGV("%s: exit", __func__);
724 return 0;
725}
726
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700727int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700728 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800729{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530730 int i, num_devices = 0;
731 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700732 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
733
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800734 if (snd_device < SND_DEVICE_MIN ||
735 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800736 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800737 return -EINVAL;
738 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739
740 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700741
742 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
743 ALOGE("%s: Invalid sound device returned", __func__);
744 return -EINVAL;
745 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700747 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700748 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 return 0;
750 }
751
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530752
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700753 if (audio_extn_spkr_prot_is_enabled())
754 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700755
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800756 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
757 audio_extn_spkr_prot_is_enabled()) {
758 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700759 adev->snd_dev_ref_cnt[snd_device]--;
760 return -EINVAL;
761 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200762 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800763 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800764 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200765 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800766 return -EINVAL;
767 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700768 } else if (platform_split_snd_device(adev->platform,
769 snd_device,
770 &num_devices,
771 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530772 for (i = 0; i < num_devices; i++) {
773 enable_snd_device(adev, new_snd_devices[i]);
774 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800775 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530777
778 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
779 (audio_extn_a2dp_start_playback() < 0)) {
780 ALOGE(" fail to configure A2dp control path ");
781 return -EINVAL;
782 }
783
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700784 /* due to the possibility of calibration overwrite between listen
785 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700786 audio_extn_sound_trigger_update_device_status(snd_device,
787 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530788 audio_extn_listen_update_device_status(snd_device,
789 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700790 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700791 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700792 audio_extn_sound_trigger_update_device_status(snd_device,
793 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530794 audio_extn_listen_update_device_status(snd_device,
795 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700796 return -EINVAL;
797 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300798 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700799 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530800
801 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
802 !adev->native_playback_enabled &&
803 audio_is_true_native_stream_active(adev)) {
804 ALOGD("%s: %d: napb: enabling native mode in hardware",
805 __func__, __LINE__);
806 audio_route_apply_and_update_path(adev->audio_route,
807 "true-native-mode");
808 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800811 return 0;
812}
813
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700814int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700815 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530817 int i, num_devices = 0;
818 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700819 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
820
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800821 if (snd_device < SND_DEVICE_MIN ||
822 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800823 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800824 return -EINVAL;
825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
827 ALOGE("%s: device ref cnt is already 0", __func__);
828 return -EINVAL;
829 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700832
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700833 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
834 ALOGE("%s: Invalid sound device returned", __func__);
835 return -EINVAL;
836 }
837
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700839 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530840
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800841 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
842 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700843 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700844 } else if (platform_split_snd_device(adev->platform,
845 snd_device,
846 &num_devices,
847 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530848 for (i = 0; i < num_devices; i++) {
849 disable_snd_device(adev, new_snd_devices[i]);
850 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300851 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700852 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300853 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700854
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530855 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
856 audio_extn_a2dp_stop_playback();
857
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700858 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530859 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530860 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
861 adev->native_playback_enabled) {
862 ALOGD("%s: %d: napb: disabling native mode in hardware",
863 __func__, __LINE__);
864 audio_route_reset_and_update_path(adev->audio_route,
865 "true-native-mode");
866 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530867 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
868 adev->asrc_mode_enabled) {
869 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530870 disable_asrc_mode(adev);
871 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530872 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530873
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200874 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700875 audio_extn_sound_trigger_update_device_status(snd_device,
876 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530877 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800878 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 return 0;
882}
883
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700884/*
885 legend:
886 uc - existing usecase
887 new_uc - new usecase
888 d1, d11, d2 - SND_DEVICE enums
889 a1, a2 - corresponding ANDROID device enums
890 B1, B2 - backend strings
891
892case 1
893 uc->dev d1 (a1) B1
894 new_uc->dev d1 (a1), d2 (a2) B1, B2
895
896 resolution: disable and enable uc->dev on d1
897
898case 2
899 uc->dev d1 (a1) B1
900 new_uc->dev d11 (a1) B1
901
902 resolution: need to switch uc since d1 and d11 are related
903 (e.g. speaker and voice-speaker)
904 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
905
906case 3
907 uc->dev d1 (a1) B1
908 new_uc->dev d2 (a2) B2
909
910 resolution: no need to switch uc
911
912case 4
913 uc->dev d1 (a1) B1
914 new_uc->dev d2 (a2) B1
915
916 resolution: disable enable uc-dev on d2 since backends match
917 we cannot enable two streams on two different devices if they
918 share the same backend. e.g. if offload is on speaker device using
919 QUAD_MI2S backend and a low-latency stream is started on voice-handset
920 using the same backend, offload must also be switched to voice-handset.
921
922case 5
923 uc->dev d1 (a1) B1
924 new_uc->dev d1 (a1), d2 (a2) B1
925
926 resolution: disable enable uc-dev on d2 since backends match
927 we cannot enable two streams on two different devices if they
928 share the same backend.
929
930case 6
931 uc->dev d1 (a1) B1
932 new_uc->dev d2 (a1) B2
933
934 resolution: no need to switch
935
936case 7
937 uc->dev d1 (a1), d2 (a2) B1, B2
938 new_uc->dev d1 (a1) B1
939
940 resolution: no need to switch
941
942*/
943static snd_device_t derive_playback_snd_device(void * platform,
944 struct audio_usecase *uc,
945 struct audio_usecase *new_uc,
946 snd_device_t new_snd_device)
947{
948 audio_devices_t a1 = uc->stream.out->devices;
949 audio_devices_t a2 = new_uc->stream.out->devices;
950
951 snd_device_t d1 = uc->out_snd_device;
952 snd_device_t d2 = new_snd_device;
953
954 // Treat as a special case when a1 and a2 are not disjoint
955 if ((a1 != a2) && (a1 & a2)) {
956 snd_device_t d3[2];
957 int num_devices = 0;
958 int ret = platform_split_snd_device(platform,
959 popcount(a1) > 1 ? d1 : d2,
960 &num_devices,
961 d3);
962 if (ret < 0) {
963 if (ret != -ENOSYS) {
964 ALOGW("%s failed to split snd_device %d",
965 __func__,
966 popcount(a1) > 1 ? d1 : d2);
967 }
968 goto end;
969 }
970
971 // NB: case 7 is hypothetical and isn't a practical usecase yet.
972 // But if it does happen, we need to give priority to d2 if
973 // the combo devices active on the existing usecase share a backend.
974 // This is because we cannot have a usecase active on a combo device
975 // and a new usecase requests one device in this combo pair.
976 if (platform_check_backends_match(d3[0], d3[1])) {
977 return d2; // case 5
978 } else {
979 return d1; // case 1
980 }
981 } else {
982 if (platform_check_backends_match(d1, d2)) {
983 return d2; // case 2, 4
984 } else {
985 return d1; // case 6, 3
986 }
987 }
988
989end:
990 return d2; // return whatever was calculated before.
991}
992
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530994 struct audio_usecase *uc_info,
995 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700996{
997 struct listnode *node;
998 struct audio_usecase *usecase;
999 bool switch_device[AUDIO_USECASE_MAX];
1000 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001001 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301002 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 /*
1004 * This function is to make sure that all the usecases that are active on
1005 * the hardware codec backend are always routed to any one device that is
1006 * handled by the hardware codec.
1007 * For example, if low-latency and deep-buffer usecases are currently active
1008 * on speaker and out_set_parameters(headset) is received on low-latency
1009 * output, then we have to make sure deep-buffer is also switched to headset,
1010 * because of the limitation that both the devices cannot be enabled
1011 * at the same time as they share the same backend.
1012 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001013 /*
1014 * This call is to check if we need to force routing for a particular stream
1015 * If there is a backend configuration change for the device when a
1016 * new stream starts, then ADM needs to be closed and re-opened with the new
1017 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001018 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001019 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001020 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1021 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301022 /* For a2dp device reconfigure all active sessions
1023 * with new AFE encoder format based on a2dp state
1024 */
1025 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1026 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1027 audio_extn_a2dp_is_force_device_switch()) {
1028 force_routing = true;
1029 force_restart_session = true;
1030 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301031 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1032
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001033 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001034 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001035 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1037 switch_device[i] = false;
1038
1039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001041
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301042 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1043 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301044 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301045 platform_get_snd_device_name(usecase->out_snd_device),
1046 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001047 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301048 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001049 (derive_playback_snd_device(adev->platform,
1050 usecase, uc_info,
1051 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301052 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1053 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301054 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301055 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1056 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1057 ((force_restart_session) ||
1058 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301059
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301060 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1061 __func__, use_case_table[usecase->id],
1062 platform_get_snd_device_name(usecase->out_snd_device));
1063 disable_audio_route(adev, usecase);
1064 switch_device[usecase->id] = true;
1065 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001066 }
1067 }
1068
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301069 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1070 num_uc_to_switch);
1071
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001073 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301075 /* Make sure the previous devices to be disabled first and then enable the
1076 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 list_for_each(node, &adev->usecase_list) {
1078 usecase = node_to_item(node, struct audio_usecase, list);
1079 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001080 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081 }
1082 }
1083
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -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 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001088 }
1089 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 /* Re-route all the usecases on the shared backend other than the
1092 specified usecase to new snd devices */
1093 list_for_each(node, &adev->usecase_list) {
1094 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301095 /* Update the out_snd_device only before enabling the audio route */
1096 if (switch_device[usecase->id]) {
1097 usecase->out_snd_device = snd_device;
1098 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301099 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301100 use_case_table[usecase->id],
1101 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001102 /* Update voc calibration before enabling VoIP route */
1103 if (usecase->type == VOIP_CALL)
1104 status = platform_switch_voice_call_device_post(adev->platform,
1105 usecase->out_snd_device,
1106 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301107 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 }
1110 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 }
1112}
1113
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301114static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001115 struct audio_usecase *uc_info,
1116 snd_device_t snd_device)
1117{
1118 struct listnode *node;
1119 struct audio_usecase *usecase;
1120 bool switch_device[AUDIO_USECASE_MAX];
1121 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301122 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001123 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001124
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301125 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1126 snd_device);
1127 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301128
1129 /*
1130 * Make sure out devices is checked against out codec backend device and
1131 * also in devices against in codec backend. Checking out device against in
1132 * codec backend or vice versa causes issues.
1133 */
1134 if (uc_info->type == PCM_CAPTURE)
1135 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001136 /*
1137 * This function is to make sure that all the active capture usecases
1138 * are always routed to the same input sound device.
1139 * For example, if audio-record and voice-call usecases are currently
1140 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1141 * is received for voice call then we have to make sure that audio-record
1142 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1143 * because of the limitation that two devices cannot be enabled
1144 * at the same time if they share the same backend.
1145 */
1146 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1147 switch_device[i] = false;
1148
1149 list_for_each(node, &adev->usecase_list) {
1150 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301151 /*
1152 * TODO: Enhance below condition to handle BT sco/USB multi recording
1153 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001154 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001155 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301156 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301157 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301158 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001159 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001160 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001161 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1162 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001163 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001164 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 switch_device[usecase->id] = true;
1166 num_uc_to_switch++;
1167 }
1168 }
1169
1170 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001171 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001172
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301173 /* Make sure the previous devices to be disabled first and then enable the
1174 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175 list_for_each(node, &adev->usecase_list) {
1176 usecase = node_to_item(node, struct audio_usecase, list);
1177 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001179 }
1180 }
1181
1182 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 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001186 }
1187 }
1188
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001189 /* Re-route all the usecases on the shared backend other than the
1190 specified usecase to new snd devices */
1191 list_for_each(node, &adev->usecase_list) {
1192 usecase = node_to_item(node, struct audio_usecase, list);
1193 /* Update the in_snd_device only before enabling the audio route */
1194 if (switch_device[usecase->id] ) {
1195 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001196 if (usecase->type != VOICE_CALL) {
1197 /* Update voc calibration before enabling VoIP route */
1198 if (usecase->type == VOIP_CALL)
1199 status = platform_switch_voice_call_device_post(adev->platform,
1200 usecase->out_snd_device,
1201 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301202 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001203 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001204 }
1205 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001206 }
1207}
1208
Mingming Yin3a941d42016-02-17 18:08:05 -08001209static void reset_hdmi_sink_caps(struct stream_out *out) {
1210 int i = 0;
1211
1212 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1213 out->supported_channel_masks[i] = 0;
1214 }
1215 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1216 out->supported_formats[i] = 0;
1217 }
1218 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1219 out->supported_sample_rates[i] = 0;
1220 }
1221}
1222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001224static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225{
Mingming Yin3a941d42016-02-17 18:08:05 -08001226 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001227 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228
Mingming Yin3a941d42016-02-17 18:08:05 -08001229 reset_hdmi_sink_caps(out);
1230
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001231 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001232 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001233 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001234 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001235 }
1236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001238 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001239 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001240 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001241 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1242 case 6:
1243 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1244 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1245 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1246 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1247 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1248 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 break;
1250 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001251 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001252 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 break;
1254 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001255
1256 // check channel format caps
1257 i = 0;
1258 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1259 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1260 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1261 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1262 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1263 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1264 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1265 }
1266
1267 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1268 ALOGV(":%s HDMI supports DTS format", __func__);
1269 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1270 }
1271
1272 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1273 ALOGV(":%s HDMI supports DTS HD format", __func__);
1274 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1275 }
1276
1277
1278 // check sample rate caps
1279 i = 0;
1280 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1281 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1282 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1283 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1284 }
1285 }
1286
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001287 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288}
1289
Alexy Josephb1379942016-01-29 15:49:38 -08001290audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001291 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001292{
1293 struct audio_usecase *usecase;
1294 struct listnode *node;
1295
1296 list_for_each(node, &adev->usecase_list) {
1297 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001298 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001299 ALOGV("%s: usecase id %d", __func__, usecase->id);
1300 return usecase->id;
1301 }
1302 }
1303 return USECASE_INVALID;
1304}
1305
Alexy Josephb1379942016-01-29 15:49:38 -08001306struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001307 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308{
1309 struct audio_usecase *usecase;
1310 struct listnode *node;
1311
1312 list_for_each(node, &adev->usecase_list) {
1313 usecase = node_to_item(node, struct audio_usecase, list);
1314 if (usecase->id == uc_id)
1315 return usecase;
1316 }
1317 return NULL;
1318}
1319
Dhananjay Kumard4833242016-10-06 22:09:12 +05301320struct stream_in *get_next_active_input(const struct audio_device *adev)
1321{
1322 struct audio_usecase *usecase;
1323 struct listnode *node;
1324
1325 list_for_each_reverse(node, &adev->usecase_list) {
1326 usecase = node_to_item(node, struct audio_usecase, list);
1327 if (usecase->type == PCM_CAPTURE)
1328 return usecase->stream.in;
1329 }
1330 return NULL;
1331}
1332
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301333/*
1334 * is a true native playback active
1335 */
1336bool audio_is_true_native_stream_active(struct audio_device *adev)
1337{
1338 bool active = false;
1339 int i = 0;
1340 struct listnode *node;
1341
1342 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1343 ALOGV("%s:napb: not in true mode or non hdphones device",
1344 __func__);
1345 active = false;
1346 goto exit;
1347 }
1348
1349 list_for_each(node, &adev->usecase_list) {
1350 struct audio_usecase *uc;
1351 uc = node_to_item(node, struct audio_usecase, list);
1352 struct stream_out *curr_out =
1353 (struct stream_out*) uc->stream.out;
1354
1355 if (curr_out && PCM_PLAYBACK == uc->type) {
1356 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1357 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1358 uc->id, curr_out->sample_rate,
1359 curr_out->bit_width,
1360 platform_get_snd_device_name(uc->out_snd_device));
1361
1362 if (is_offload_usecase(uc->id) &&
1363 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1364 active = true;
1365 ALOGD("%s:napb:native stream detected", __func__);
1366 }
1367 }
1368 }
1369exit:
1370 return active;
1371}
1372
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301373/*
1374 * if native DSD playback active
1375 */
1376bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1377{
1378 bool active = false;
1379 struct listnode *node = NULL;
1380 struct audio_usecase *uc = NULL;
1381 struct stream_out *curr_out = NULL;
1382
1383 list_for_each(node, &adev->usecase_list) {
1384 uc = node_to_item(node, struct audio_usecase, list);
1385 curr_out = (struct stream_out*) uc->stream.out;
1386
1387 if (curr_out && PCM_PLAYBACK == uc->type &&
1388 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1389 active = true;
1390 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301391 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301392 }
1393 }
1394 return active;
1395}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301396
1397static bool force_device_switch(struct audio_usecase *usecase)
1398{
1399 bool ret = false;
1400 bool is_it_true_mode = false;
1401
1402 if (is_offload_usecase(usecase->id) &&
1403 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001404 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1405 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1406 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301407 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1408 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1409 (!is_it_true_mode && adev->native_playback_enabled)){
1410 ret = true;
1411 ALOGD("napb: time to toggle native mode");
1412 }
1413 }
1414
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301415 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301416 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1417 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301418 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001419 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301420 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301421 ALOGD("Force a2dp device switch to update new encoder config");
1422 ret = true;
1423 }
1424
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301425 return ret;
1426}
1427
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001428int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001430 snd_device_t out_snd_device = SND_DEVICE_NONE;
1431 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432 struct audio_usecase *usecase = NULL;
1433 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001434 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001435 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001436 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001437 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301439 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 usecase = get_usecase_from_list(adev, uc_id);
1442 if (usecase == NULL) {
1443 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1444 return -EINVAL;
1445 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001447 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001448 (usecase->type == VOIP_CALL) ||
1449 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301450 if(usecase->stream.out == NULL) {
1451 ALOGE("%s: stream.out is NULL", __func__);
1452 return -EINVAL;
1453 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001454 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001455 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001456 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 usecase->devices = usecase->stream.out->devices;
1458 } else {
1459 /*
1460 * If the voice call is active, use the sound devices of voice call usecase
1461 * so that it would not result any device switch. All the usecases will
1462 * be switched to new device when select_devices() is called for voice call
1463 * usecase. This is to avoid switching devices for voice call when
1464 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001465 * choose voice call device only if the use case device is
1466 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001468 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001469 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001470 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001471 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1472 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301473 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1474 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001475 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 in_snd_device = vc_usecase->in_snd_device;
1477 out_snd_device = vc_usecase->out_snd_device;
1478 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001479 } else if (voice_extn_compress_voip_is_active(adev)) {
1480 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001481 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001482 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1483 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001484 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001485 in_snd_device = voip_usecase->in_snd_device;
1486 out_snd_device = voip_usecase->out_snd_device;
1487 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001488 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001489 hfp_ucid = audio_extn_hfp_get_usecase();
1490 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001491 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001492 in_snd_device = hfp_usecase->in_snd_device;
1493 out_snd_device = hfp_usecase->out_snd_device;
1494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 }
1496 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301497 if (usecase->stream.out == NULL) {
1498 ALOGE("%s: stream.out is NULL", __func__);
1499 return -EINVAL;
1500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 usecase->devices = usecase->stream.out->devices;
1502 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001503 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001504 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001505 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001506 if (usecase->stream.out == adev->primary_output &&
1507 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001508 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001509 select_devices(adev, adev->active_input->usecase);
1510 }
1511 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001512 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301513 if (usecase->stream.in == NULL) {
1514 ALOGE("%s: stream.in is NULL", __func__);
1515 return -EINVAL;
1516 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 usecase->devices = usecase->stream.in->device;
1518 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001519 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001520 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001521 if (adev->active_input &&
1522 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301523 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1524 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1525 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001526 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001527 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001528 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1529 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001530 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001531 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001532 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001533 }
1534 }
1535
1536 if (out_snd_device == usecase->out_snd_device &&
1537 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301538
1539 if (!force_device_switch(usecase))
1540 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 }
1542
sangwoobc677242013-08-08 16:53:43 +09001543 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001544 out_snd_device, platform_get_snd_device_name(out_snd_device),
1545 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 /*
1548 * Limitation: While in call, to do a device switch we need to disable
1549 * and enable both RX and TX devices though one of them is same as current
1550 * device.
1551 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001552 if ((usecase->type == VOICE_CALL) &&
1553 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1554 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001555 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001556 }
1557
1558 if (((usecase->type == VOICE_CALL) ||
1559 (usecase->type == VOIP_CALL)) &&
1560 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1561 /* Disable sidetone only if voice/voip call already exists */
1562 if (voice_is_call_state_active(adev) ||
1563 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001564 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001565
1566 /* Disable aanc only if voice call exists */
1567 if (voice_is_call_state_active(adev))
1568 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001569 }
1570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 /* Disable current sound devices */
1572 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001573 disable_audio_route(adev, usecase);
1574 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 }
1576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001578 disable_audio_route(adev, usecase);
1579 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580 }
1581
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001582 /* Applicable only on the targets that has external modem.
1583 * New device information should be sent to modem before enabling
1584 * the devices to reduce in-call device switch time.
1585 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001586 if ((usecase->type == VOICE_CALL) &&
1587 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1588 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001589 status = platform_switch_voice_call_enable_device_config(adev->platform,
1590 out_snd_device,
1591 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001592 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001593
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001594 /* Enable new sound devices */
1595 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001596 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301597 if (platform_check_codec_asrc_support(adev->platform))
1598 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001599 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 }
1601
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001602 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301603 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001605 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001606
Avinash Vaish71a8b972014-07-24 15:36:33 +05301607 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001608 status = platform_switch_voice_call_device_post(adev->platform,
1609 out_snd_device,
1610 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301611 enable_audio_route_for_voice_usecases(adev, usecase);
1612 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001613
sangwoo170731f2013-06-08 15:36:36 +09001614 usecase->in_snd_device = in_snd_device;
1615 usecase->out_snd_device = out_snd_device;
1616
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301617 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1618 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301619 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001620 if ((24 == usecase->stream.out->bit_width) &&
1621 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1622 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1623 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1624 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1625 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1626 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1627 /*
1628 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1629 * configured device sample rate, if not update the COPP rate to be equal to the
1630 * device sample rate, else open COPP at stream sample rate
1631 */
1632 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1633 usecase->stream.out->sample_rate,
1634 &usecase->stream.out->app_type_cfg.sample_rate);
1635 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1636 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1637 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1638 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1639 }
1640
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001641 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001642 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001643 audio_extn_gef_notify_device_config(
1644 usecase->stream.out->devices,
1645 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001646 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001647 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001648 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301649 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001650 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001651
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001652 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001653 /* Enable aanc only if voice call exists */
1654 if (voice_is_call_state_active(adev))
1655 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1656
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001657 /* Enable sidetone only if other voice/voip call already exists */
1658 if (voice_is_call_state_active(adev) ||
1659 voice_extn_compress_voip_is_started(adev))
1660 voice_set_sidetone(adev, out_snd_device, true);
1661 }
1662
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001663 /* Applicable only on the targets that has external modem.
1664 * Enable device command should be sent to modem only after
1665 * enabling voice call mixer controls
1666 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001667 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001668 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1669 out_snd_device,
1670 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301671 ALOGD("%s: done",__func__);
1672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 return status;
1674}
1675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676static int stop_input_stream(struct stream_in *in)
1677{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301678 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 struct audio_usecase *uc_info;
1680 struct audio_device *adev = in->dev;
1681
Eric Laurent994a6932013-07-17 11:51:42 -07001682 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 uc_info = get_usecase_from_list(adev, in->usecase);
1685 if (uc_info == NULL) {
1686 ALOGE("%s: Could not find the usecase (%d) in the list",
1687 __func__, in->usecase);
1688 return -EINVAL;
1689 }
1690
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001691 /* Close in-call recording streams */
1692 voice_check_and_stop_incall_rec_usecase(adev, in);
1693
Eric Laurent150dbfe2013-02-27 14:31:02 -08001694 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001695 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001696
1697 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001698 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001700 list_remove(&uc_info->list);
1701 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001703 adev->active_input = get_next_active_input(adev);
1704
Eric Laurent994a6932013-07-17 11:51:42 -07001705 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706 return ret;
1707}
1708
1709int start_input_stream(struct stream_in *in)
1710{
1711 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001712 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 struct audio_usecase *uc_info;
1714 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301715 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Mingming Yin2664a5b2015-09-03 10:53:11 -07001717 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1718 if (get_usecase_from_list(adev, usecase) == NULL)
1719 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301720 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1721 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001722
Naresh Tanniru80659832014-06-04 18:17:56 +05301723
1724 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301725 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301726 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301727 goto error_config;
1728 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301729
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001730 /* Check if source matches incall recording usecase criteria */
1731 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1732 if (ret)
1733 goto error_config;
1734 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001735 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1736
1737 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1738 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1739 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001740 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001741 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001742
Eric Laurentb23d5282013-05-14 15:27:20 -07001743 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 if (in->pcm_device_id < 0) {
1745 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1746 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001747 ret = -EINVAL;
1748 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750
1751 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001753
1754 if (!uc_info) {
1755 ret = -ENOMEM;
1756 goto error_config;
1757 }
1758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759 uc_info->id = in->usecase;
1760 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001761 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762 uc_info->devices = in->device;
1763 uc_info->in_snd_device = SND_DEVICE_NONE;
1764 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001766 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301767 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1768 adev->perf_lock_opts,
1769 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301772 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1773 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001774
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301775 if (audio_extn_cin_attached_usecase(in->usecase)) {
1776 ret = audio_extn_cin_start_input_stream(in);
1777 if (ret)
1778 goto error_open;
1779 else
1780 goto done_open;
1781 }
1782
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001783 unsigned int flags = PCM_IN;
1784 unsigned int pcm_open_retry_count = 0;
1785
1786 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1787 flags |= PCM_MMAP | PCM_NOIRQ;
1788 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001789 } else if (in->realtime) {
1790 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001791 }
1792
1793 while (1) {
1794 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1795 flags, &in->config);
1796 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1797 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1798 if (in->pcm != NULL) {
1799 pcm_close(in->pcm);
1800 in->pcm = NULL;
1801 }
1802 if (pcm_open_retry_count-- == 0) {
1803 ret = -EIO;
1804 goto error_open;
1805 }
1806 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1807 continue;
1808 }
1809 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001811
1812 ALOGV("%s: pcm_prepare", __func__);
1813 ret = pcm_prepare(in->pcm);
1814 if (ret < 0) {
1815 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1816 pcm_close(in->pcm);
1817 in->pcm = NULL;
1818 goto error_open;
1819 }
1820
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001821 register_in_stream(in);
1822 if (in->realtime) {
1823 ret = pcm_start(in->pcm);
1824 if (ret < 0)
1825 goto error_open;
1826 }
1827
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301828done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301829 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001830 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001831
Eric Laurentc8400632013-02-14 19:04:54 -08001832 return ret;
1833
1834error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301835 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001837error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301838 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301839 /*
1840 * sleep 50ms to allow sufficient time for kernel
1841 * drivers to recover incases like SSR.
1842 */
1843 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001844 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001845
1846 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847}
1848
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001849void lock_input_stream(struct stream_in *in)
1850{
1851 pthread_mutex_lock(&in->pre_lock);
1852 pthread_mutex_lock(&in->lock);
1853 pthread_mutex_unlock(&in->pre_lock);
1854}
1855
1856void lock_output_stream(struct stream_out *out)
1857{
1858 pthread_mutex_lock(&out->pre_lock);
1859 pthread_mutex_lock(&out->lock);
1860 pthread_mutex_unlock(&out->pre_lock);
1861}
1862
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001863/* must be called with out->lock locked */
1864static int send_offload_cmd_l(struct stream_out* out, int command)
1865{
1866 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1867
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001868 if (!cmd) {
1869 ALOGE("failed to allocate mem for command 0x%x", command);
1870 return -ENOMEM;
1871 }
1872
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001873 ALOGVV("%s %d", __func__, command);
1874
1875 cmd->cmd = command;
1876 list_add_tail(&out->offload_cmd_list, &cmd->node);
1877 pthread_cond_signal(&out->offload_cond);
1878 return 0;
1879}
1880
1881/* must be called iwth out->lock locked */
1882static void stop_compressed_output_l(struct stream_out *out)
1883{
1884 out->offload_state = OFFLOAD_STATE_IDLE;
1885 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001886 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001887 if (out->compr != NULL) {
1888 compress_stop(out->compr);
1889 while (out->offload_thread_blocked) {
1890 pthread_cond_wait(&out->cond, &out->lock);
1891 }
1892 }
1893}
1894
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001895bool is_offload_usecase(audio_usecase_t uc_id)
1896{
1897 unsigned int i;
1898 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1899 if (uc_id == offload_usecases[i])
1900 return true;
1901 }
1902 return false;
1903}
1904
vivek mehta446c3962015-09-14 10:57:35 -07001905static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001906{
vivek mehta446c3962015-09-14 10:57:35 -07001907 audio_usecase_t ret_uc = USECASE_INVALID;
1908 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001909 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001910 if (!adev->multi_offload_enable) {
1911 if (is_direct_pcm)
1912 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1913 else
1914 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001915
vivek mehta446c3962015-09-14 10:57:35 -07001916 pthread_mutex_lock(&adev->lock);
1917 if (get_usecase_from_list(adev, ret_uc) != NULL)
1918 ret_uc = USECASE_INVALID;
1919 pthread_mutex_unlock(&adev->lock);
1920
1921 return ret_uc;
1922 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001923
1924 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001925 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1926 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1927 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1928 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001929 break;
1930 }
1931 }
vivek mehta446c3962015-09-14 10:57:35 -07001932
1933 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1934 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001935}
1936
1937static void free_offload_usecase(struct audio_device *adev,
1938 audio_usecase_t uc_id)
1939{
vivek mehta446c3962015-09-14 10:57:35 -07001940 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001941 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001942
1943 if (!adev->multi_offload_enable)
1944 return;
1945
1946 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1947 if (offload_usecases[offload_uc_index] == uc_id) {
1948 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001949 break;
1950 }
1951 }
1952 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1953}
1954
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001955static void *offload_thread_loop(void *context)
1956{
1957 struct stream_out *out = (struct stream_out *) context;
1958 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001959 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001961 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1962 set_sched_policy(0, SP_FOREGROUND);
1963 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1964
1965 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001966 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001967 for (;;) {
1968 struct offload_cmd *cmd = NULL;
1969 stream_callback_event_t event;
1970 bool send_callback = false;
1971
1972 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1973 __func__, list_empty(&out->offload_cmd_list),
1974 out->offload_state);
1975 if (list_empty(&out->offload_cmd_list)) {
1976 ALOGV("%s SLEEPING", __func__);
1977 pthread_cond_wait(&out->offload_cond, &out->lock);
1978 ALOGV("%s RUNNING", __func__);
1979 continue;
1980 }
1981
1982 item = list_head(&out->offload_cmd_list);
1983 cmd = node_to_item(item, struct offload_cmd, node);
1984 list_remove(item);
1985
1986 ALOGVV("%s STATE %d CMD %d out->compr %p",
1987 __func__, out->offload_state, cmd->cmd, out->compr);
1988
1989 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1990 free(cmd);
1991 break;
1992 }
1993
1994 if (out->compr == NULL) {
1995 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001996 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 pthread_cond_signal(&out->cond);
1998 continue;
1999 }
2000 out->offload_thread_blocked = true;
2001 pthread_mutex_unlock(&out->lock);
2002 send_callback = false;
2003 switch(cmd->cmd) {
2004 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002005 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002007 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002008 send_callback = true;
2009 event = STREAM_CBK_EVENT_WRITE_READY;
2010 break;
2011 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002012 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302013 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002014 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302015 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002016 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302017 if (ret < 0)
2018 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302019 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302020 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002021 compress_drain(out->compr);
2022 else
2023 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302024 if (ret != -ENETRESET) {
2025 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302026 pthread_mutex_lock(&out->lock);
2027 out->send_new_metadata = 1;
2028 out->send_next_track_params = true;
2029 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302030 event = STREAM_CBK_EVENT_DRAIN_READY;
2031 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2032 } else
2033 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002034 break;
2035 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002036 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002038 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 send_callback = true;
2040 event = STREAM_CBK_EVENT_DRAIN_READY;
2041 break;
2042 default:
2043 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2044 break;
2045 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002046 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002047 out->offload_thread_blocked = false;
2048 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002049 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002050 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 free(cmd);
2054 }
2055
2056 pthread_cond_signal(&out->cond);
2057 while (!list_empty(&out->offload_cmd_list)) {
2058 item = list_head(&out->offload_cmd_list);
2059 list_remove(item);
2060 free(node_to_item(item, struct offload_cmd, node));
2061 }
2062 pthread_mutex_unlock(&out->lock);
2063
2064 return NULL;
2065}
2066
2067static int create_offload_callback_thread(struct stream_out *out)
2068{
2069 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2070 list_init(&out->offload_cmd_list);
2071 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2072 offload_thread_loop, out);
2073 return 0;
2074}
2075
2076static int destroy_offload_callback_thread(struct stream_out *out)
2077{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002078 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 stop_compressed_output_l(out);
2080 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2081
2082 pthread_mutex_unlock(&out->lock);
2083 pthread_join(out->offload_thread, (void **) NULL);
2084 pthread_cond_destroy(&out->offload_cond);
2085
2086 return 0;
2087}
2088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089static int stop_output_stream(struct stream_out *out)
2090{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302091 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 struct audio_usecase *uc_info;
2093 struct audio_device *adev = out->dev;
2094
Eric Laurent994a6932013-07-17 11:51:42 -07002095 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002096 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 uc_info = get_usecase_from_list(adev, out->usecase);
2098 if (uc_info == NULL) {
2099 ALOGE("%s: Could not find the usecase (%d) in the list",
2100 __func__, out->usecase);
2101 return -EINVAL;
2102 }
2103
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002104 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302105 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002106 if (adev->visualizer_stop_output != NULL)
2107 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002108
2109 audio_extn_dts_remove_state_notifier_node(out->usecase);
2110
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002111 if (adev->offload_effects_stop_output != NULL)
2112 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2113 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002114
Eric Laurent150dbfe2013-02-27 14:31:02 -08002115 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002116 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002117
2118 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002119 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002121 list_remove(&uc_info->list);
2122 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002124 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302125 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002126 ALOGV("Disable passthrough , reset mixer to pcm");
2127 /* NO_PASSTHROUGH */
2128 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002129 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002130 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2131 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002132
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302133 /* Must be called after removing the usecase from list */
2134 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302135 audio_extn_keep_alive_start();
2136
Eric Laurent994a6932013-07-17 11:51:42 -07002137 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 return ret;
2139}
2140
2141int start_output_stream(struct stream_out *out)
2142{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 struct audio_usecase *uc_info;
2145 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302146 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002148 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2149 ret = -EINVAL;
2150 goto error_config;
2151 }
2152
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302153 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2154 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2155 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302156
Naresh Tanniru80659832014-06-04 18:17:56 +05302157 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302158 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302159 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302160 goto error_config;
2161 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302162
Eric Laurentb23d5282013-05-14 15:27:20 -07002163 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 if (out->pcm_device_id < 0) {
2165 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2166 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002167 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002168 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 }
2170
2171 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002172
2173 if (!uc_info) {
2174 ret = -ENOMEM;
2175 goto error_config;
2176 }
2177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 uc_info->id = out->usecase;
2179 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002180 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 uc_info->devices = out->devices;
2182 uc_info->in_snd_device = SND_DEVICE_NONE;
2183 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002184 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302186 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2187 adev->perf_lock_opts,
2188 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302189
2190 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2191 audio_extn_keep_alive_stop();
2192 if (audio_extn_passthru_is_enabled() &&
2193 audio_extn_passthru_is_passthrough_stream(out)) {
2194 audio_extn_passthru_on_start(out);
2195 audio_extn_passthru_update_stream_configuration(adev, out);
2196 }
2197 }
2198
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002199 select_devices(adev, out->usecase);
2200
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002201 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2202 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002203 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002204 unsigned int flags = PCM_OUT;
2205 unsigned int pcm_open_retry_count = 0;
2206 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2207 flags |= PCM_MMAP | PCM_NOIRQ;
2208 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002209 } else if (out->realtime) {
2210 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002211 } else
2212 flags |= PCM_MONOTONIC;
2213
2214 while (1) {
2215 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2216 flags, &out->config);
2217 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2218 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2219 if (out->pcm != NULL) {
2220 pcm_close(out->pcm);
2221 out->pcm = NULL;
2222 }
2223 if (pcm_open_retry_count-- == 0) {
2224 ret = -EIO;
2225 goto error_open;
2226 }
2227 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2228 continue;
2229 }
2230 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002232
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002233 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2234 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002235
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002236 ALOGV("%s: pcm_prepare", __func__);
2237 if (pcm_is_ready(out->pcm)) {
2238 ret = pcm_prepare(out->pcm);
2239 if (ret < 0) {
2240 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2241 pcm_close(out->pcm);
2242 out->pcm = NULL;
2243 goto error_open;
2244 }
2245 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002247 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2248 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002250 out->compr = compress_open(adev->snd_card,
2251 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252 COMPRESS_IN, &out->compr_config);
2253 if (out->compr && !is_compress_ready(out->compr)) {
2254 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2255 compress_close(out->compr);
2256 out->compr = NULL;
2257 ret = -EIO;
2258 goto error_open;
2259 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302260 /* compress_open sends params of the track, so reset the flag here */
2261 out->is_compr_metadata_avail = false;
2262
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263 if (out->offload_callback)
2264 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002265
Fred Oh3f43e742015-03-04 18:42:34 -08002266 /* Since small bufs uses blocking writes, a write will be blocked
2267 for the default max poll time (20s) in the event of an SSR.
2268 Reduce the poll time to observe and deal with SSR faster.
2269 */
Ashish Jain5106d362016-05-11 19:23:33 +05302270 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002271 compress_set_max_poll_wait(out->compr, 1000);
2272 }
2273
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002274 audio_extn_dts_create_state_notifier_node(out->usecase);
2275 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2276 popcount(out->channel_mask),
2277 out->playback_started);
2278
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002279#ifdef DS1_DOLBY_DDP_ENABLED
2280 if (audio_extn_is_dolby_format(out->format))
2281 audio_extn_dolby_send_ddp_endp_params(adev);
2282#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302283 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002284 if (adev->visualizer_start_output != NULL)
2285 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2286 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302287 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002288 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002289 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002291
2292 if (ret == 0) {
2293 register_out_stream(out);
2294 if (out->realtime) {
2295 ret = pcm_start(out->pcm);
2296 if (ret < 0)
2297 goto error_open;
2298 }
2299 }
2300
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302301 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002302 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002303
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002304 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302306 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002308error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302309 /*
2310 * sleep 50ms to allow sufficient time for kernel
2311 * drivers to recover incases like SSR.
2312 */
2313 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002314 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315}
2316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317static int check_input_parameters(uint32_t sample_rate,
2318 audio_format_t format,
2319 int channel_count)
2320{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002321 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302323 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2324 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2325 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002326 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302327 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002328
2329 switch (channel_count) {
2330 case 1:
2331 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302332 case 3:
2333 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002334 case 6:
2335 break;
2336 default:
2337 ret = -EINVAL;
2338 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339
2340 switch (sample_rate) {
2341 case 8000:
2342 case 11025:
2343 case 12000:
2344 case 16000:
2345 case 22050:
2346 case 24000:
2347 case 32000:
2348 case 44100:
2349 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302350 case 96000:
2351 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 break;
2353 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002354 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 }
2356
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002357 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358}
2359
2360static size_t get_input_buffer_size(uint32_t sample_rate,
2361 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002362 int channel_count,
2363 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364{
2365 size_t size = 0;
2366
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002367 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2368 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002370 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002371 if (is_low_latency)
2372 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302373
2374 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002376 /* make sure the size is multiple of 32 bytes
2377 * At 48 kHz mono 16-bit PCM:
2378 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2379 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2380 */
2381 size += 0x1f;
2382 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002383
2384 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385}
2386
Ashish Jain058165c2016-09-28 23:18:48 +05302387static size_t get_output_period_size(uint32_t sample_rate,
2388 audio_format_t format,
2389 int channel_count,
2390 int duration /*in millisecs*/)
2391{
2392 size_t size = 0;
2393 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2394
2395 if ((duration == 0) || (sample_rate == 0) ||
2396 (bytes_per_sample == 0) || (channel_count == 0)) {
2397 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2398 bytes_per_sample, channel_count);
2399 return -EINVAL;
2400 }
2401
2402 size = (sample_rate *
2403 duration *
2404 bytes_per_sample *
2405 channel_count) / 1000;
2406 /*
2407 * To have same PCM samples for all channels, the buffer size requires to
2408 * be multiple of (number of channels * bytes per sample)
2409 * For writes to succeed, the buffer must be written at address which is multiple of 32
2410 */
2411 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2412
2413 return (size/(channel_count * bytes_per_sample));
2414}
2415
Ashish Jain5106d362016-05-11 19:23:33 +05302416static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2417{
2418 uint64_t actual_frames_rendered = 0;
2419 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2420
2421 /* This adjustment accounts for buffering after app processor.
2422 * It is based on estimated DSP latency per use case, rather than exact.
2423 */
2424 int64_t platform_latency = platform_render_latency(out->usecase) *
2425 out->sample_rate / 1000000LL;
2426
2427 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2428 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2429 * hence only estimate.
2430 */
2431 int64_t signed_frames = out->written - kernel_buffer_size;
2432
2433 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2434
2435 if (signed_frames > 0)
2436 actual_frames_rendered = signed_frames;
2437
2438 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2439 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2440 (long long int)out->written, (int)kernel_buffer_size,
2441 audio_bytes_per_sample(out->compr_config.codec->format),
2442 popcount(out->channel_mask));
2443
2444 return actual_frames_rendered;
2445}
2446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452}
2453
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002454static int out_set_sample_rate(struct audio_stream *stream __unused,
2455 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456{
2457 return -ENOSYS;
2458}
2459
2460static size_t out_get_buffer_size(const struct audio_stream *stream)
2461{
2462 struct stream_out *out = (struct stream_out *)stream;
2463
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002464 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002465 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002466 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2467 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302468 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302469 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002471 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002472 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473}
2474
2475static uint32_t out_get_channels(const struct audio_stream *stream)
2476{
2477 struct stream_out *out = (struct stream_out *)stream;
2478
2479 return out->channel_mask;
2480}
2481
2482static audio_format_t out_get_format(const struct audio_stream *stream)
2483{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 struct stream_out *out = (struct stream_out *)stream;
2485
2486 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487}
2488
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002489static int out_set_format(struct audio_stream *stream __unused,
2490 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491{
2492 return -ENOSYS;
2493}
2494
2495static int out_standby(struct audio_stream *stream)
2496{
2497 struct stream_out *out = (struct stream_out *)stream;
2498 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302500 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2501 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002503 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002505 if (adev->adm_deregister_stream)
2506 adev->adm_deregister_stream(adev->adm_data, out->handle);
2507
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002508 if (is_offload_usecase(out->usecase))
2509 stop_compressed_output_l(out);
2510
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002511 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002513 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2514 voice_extn_compress_voip_close_output_stream(stream);
2515 pthread_mutex_unlock(&adev->lock);
2516 pthread_mutex_unlock(&out->lock);
2517 ALOGD("VOIP output entered standby");
2518 return 0;
2519 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002520 if (out->pcm) {
2521 pcm_close(out->pcm);
2522 out->pcm = NULL;
2523 }
2524 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002525 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302526 out->send_next_track_params = false;
2527 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002528 out->gapless_mdata.encoder_delay = 0;
2529 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 if (out->compr != NULL) {
2531 compress_close(out->compr);
2532 out->compr = NULL;
2533 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002536 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 }
2538 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302539 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 return 0;
2541}
2542
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002543static int out_dump(const struct audio_stream *stream __unused,
2544 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545{
2546 return 0;
2547}
2548
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002549static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2550{
2551 int ret = 0;
2552 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002553
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002554 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002555 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002556 return -EINVAL;
2557 }
2558
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302559 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002560
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002561 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2562 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302563 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002564 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002565 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2566 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302567 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002568 }
2569
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002570 ALOGV("%s new encoder delay %u and padding %u", __func__,
2571 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2572
2573 return 0;
2574}
2575
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002576static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2577{
2578 return out == adev->primary_output || out == adev->voice_tx_output;
2579}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2582{
2583 struct stream_out *out = (struct stream_out *)stream;
2584 struct audio_device *adev = out->dev;
2585 struct str_parms *parms;
2586 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002587 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588
sangwoobc677242013-08-08 16:53:43 +09002589 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002590 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302592 if (!parms)
2593 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002594 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2595 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002597 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002598 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002600 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002601 * When HDMI cable is unplugged the music playback is paused and
2602 * the policy manager sends routing=0. But the audioflinger continues
2603 * to write data until standby time (3sec). As the HDMI core is
2604 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002605 * Avoid this by routing audio to speaker until standby.
2606 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002607 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2608 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302609 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002610 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2611 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002612 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302613 /*
2614 * When A2DP is disconnected the
2615 * music playback is paused and the policy manager sends routing=0
2616 * But the audioflingercontinues to write data until standby time
2617 * (3sec). As BT is turned off, the write gets blocked.
2618 * Avoid this by routing audio to speaker until standby.
2619 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002620 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302621 (val == AUDIO_DEVICE_NONE)) {
2622 val = AUDIO_DEVICE_OUT_SPEAKER;
2623 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302624 /* To avoid a2dp to sco overlapping force route BT usecases
2625 * to speaker based on Phone state
2626 */
Ashish Jainc597d102016-12-12 10:31:34 +05302627 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2628 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2629 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2630 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302631 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2632 (adev->mode == AUDIO_MODE_IN_CALL))) {
2633 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2634 val = AUDIO_DEVICE_OUT_SPEAKER;
2635 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002636 /*
2637 * select_devices() call below switches all the usecases on the same
2638 * backend to the new device. Refer to check_usecases_codec_backend() in
2639 * the select_devices(). But how do we undo this?
2640 *
2641 * For example, music playback is active on headset (deep-buffer usecase)
2642 * and if we go to ringtones and select a ringtone, low-latency usecase
2643 * will be started on headset+speaker. As we can't enable headset+speaker
2644 * and headset devices at the same time, select_devices() switches the music
2645 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2646 * So when the ringtone playback is completed, how do we undo the same?
2647 *
2648 * We are relying on the out_set_parameters() call on deep-buffer output,
2649 * once the ringtone playback is ended.
2650 * NOTE: We should not check if the current devices are same as new devices.
2651 * Because select_devices() must be called to switch back the music
2652 * playback to headset.
2653 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002654 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002655 audio_devices_t new_dev = val;
2656 bool same_dev = out->devices == new_dev;
2657 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002658
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002659 if (output_drives_call(adev, out)) {
2660 if(!voice_is_in_call(adev)) {
2661 if (adev->mode == AUDIO_MODE_IN_CALL) {
2662 adev->current_call_output = out;
2663 ret = voice_start_call(adev);
2664 }
2665 } else {
2666 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002667 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002668 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002669 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002670
2671 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002672 if (!same_dev) {
2673 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302674 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2675 adev->perf_lock_opts,
2676 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002677 if (adev->adm_on_routing_change)
2678 adev->adm_on_routing_change(adev->adm_data,
2679 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002680 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002681 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302682 if (!same_dev)
2683 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002684 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002685 }
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002688 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002690
2691 if (out == adev->primary_output) {
2692 pthread_mutex_lock(&adev->lock);
2693 audio_extn_set_parameters(adev, parms);
2694 pthread_mutex_unlock(&adev->lock);
2695 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002696 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002697 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002698 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002699
2700 audio_extn_dts_create_state_notifier_node(out->usecase);
2701 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2702 popcount(out->channel_mask),
2703 out->playback_started);
2704
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002705 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002706 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002707
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302708 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2709 if (err >= 0) {
2710 strlcpy(out->profile, value, sizeof(out->profile));
2711 ALOGV("updating stream profile with value '%s'", out->profile);
2712 lock_output_stream(out);
2713 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2714 &adev->streams_output_cfg_list,
2715 out->devices, out->flags, out->format,
2716 out->sample_rate, out->bit_width,
2717 out->channel_mask, out->profile,
2718 &out->app_type_cfg);
2719 pthread_mutex_unlock(&out->lock);
2720 }
2721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302723error:
Eric Laurent994a6932013-07-17 11:51:42 -07002724 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 return ret;
2726}
2727
2728static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2729{
2730 struct stream_out *out = (struct stream_out *)stream;
2731 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002732 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 char value[256];
2734 struct str_parms *reply = str_parms_create();
2735 size_t i, j;
2736 int ret;
2737 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002738
2739 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002740 if (reply) {
2741 str_parms_destroy(reply);
2742 }
2743 if (query) {
2744 str_parms_destroy(query);
2745 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002746 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2747 return NULL;
2748 }
2749
Eric Laurent994a6932013-07-17 11:51:42 -07002750 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2752 if (ret >= 0) {
2753 value[0] = '\0';
2754 i = 0;
2755 while (out->supported_channel_masks[i] != 0) {
2756 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2757 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2758 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002759 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002761 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 first = false;
2763 break;
2764 }
2765 }
2766 i++;
2767 }
2768 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2769 str = str_parms_to_str(reply);
2770 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002771 voice_extn_out_get_parameters(out, query, reply);
2772 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002773 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002774 free(str);
2775 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002778
Alexy Joseph62142aa2015-11-16 15:10:34 -08002779
2780 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2781 if (ret >= 0) {
2782 value[0] = '\0';
2783 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2784 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302785 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002786 } else {
2787 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302788 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002789 }
2790 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002791 if (str)
2792 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002793 str = str_parms_to_str(reply);
2794 }
2795
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002796 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2797 if (ret >= 0) {
2798 value[0] = '\0';
2799 i = 0;
2800 first = true;
2801 while (out->supported_formats[i] != 0) {
2802 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2803 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2804 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002805 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002806 }
2807 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2808 first = false;
2809 break;
2810 }
2811 }
2812 i++;
2813 }
2814 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002815 if (str)
2816 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002817 str = str_parms_to_str(reply);
2818 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002819
2820 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2821 if (ret >= 0) {
2822 value[0] = '\0';
2823 i = 0;
2824 first = true;
2825 while (out->supported_sample_rates[i] != 0) {
2826 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2827 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2828 if (!first) {
2829 strlcat(value, "|", sizeof(value));
2830 }
2831 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2832 first = false;
2833 break;
2834 }
2835 }
2836 i++;
2837 }
2838 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2839 if (str)
2840 free(str);
2841 str = str_parms_to_str(reply);
2842 }
2843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 str_parms_destroy(query);
2845 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002846 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 return str;
2848}
2849
2850static uint32_t out_get_latency(const struct audio_stream_out *stream)
2851{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002852 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002854 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855
Alexy Josephaa54c872014-12-03 02:46:47 -08002856 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002857 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002858 } else if (out->realtime) {
2859 // since the buffer won't be filled up faster than realtime,
2860 // return a smaller number
2861 if (out->config.rate)
2862 period_ms = (out->af_period_multiplier * out->config.period_size *
2863 1000) / (out->config.rate);
2864 else
2865 period_ms = 0;
2866 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002867 } else {
2868 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002870 }
2871
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302872 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002873 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874}
2875
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302876static float AmpToDb(float amplification)
2877{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302878 float db = DSD_VOLUME_MIN_DB;
2879 if (amplification > 0) {
2880 db = 20 * log10(amplification);
2881 if(db < DSD_VOLUME_MIN_DB)
2882 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302883 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302884 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302885}
2886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887static int out_set_volume(struct audio_stream_out *stream, float left,
2888 float right)
2889{
Eric Laurenta9024de2013-04-04 09:19:12 -07002890 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 int volume[2];
2892
Eric Laurenta9024de2013-04-04 09:19:12 -07002893 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2894 /* only take left channel into account: the API is for stereo anyway */
2895 out->muted = (left == 0.0f);
2896 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002897 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302898 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002899 /*
2900 * Set mute or umute on HDMI passthrough stream.
2901 * Only take left channel into account.
2902 * Mute is 0 and unmute 1
2903 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302904 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302905 } else if (out->format == AUDIO_FORMAT_DSD){
2906 char mixer_ctl_name[128] = "DSD Volume";
2907 struct audio_device *adev = out->dev;
2908 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2909
2910 if (!ctl) {
2911 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2912 __func__, mixer_ctl_name);
2913 return -EINVAL;
2914 }
2915 volume[0] = (int)(AmpToDb(left));
2916 volume[1] = (int)(AmpToDb(right));
2917 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2918 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002919 } else {
2920 char mixer_ctl_name[128];
2921 struct audio_device *adev = out->dev;
2922 struct mixer_ctl *ctl;
2923 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002924 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002926 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2927 "Compress Playback %d Volume", pcm_device_id);
2928 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2929 if (!ctl) {
2930 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2931 __func__, mixer_ctl_name);
2932 return -EINVAL;
2933 }
2934 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2935 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2936 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2937 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002939 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 return -ENOSYS;
2942}
2943
2944static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2945 size_t bytes)
2946{
2947 struct stream_out *out = (struct stream_out *)stream;
2948 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302949 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002950 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002952 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302953
Naresh Tanniru80659832014-06-04 18:17:56 +05302954 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002955
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302956 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302957 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302958 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2959 pthread_mutex_unlock(&out->lock);
2960 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302961 } else {
2962 /* increase written size during SSR to avoid mismatch
2963 * with the written frames count in AF
2964 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002965 // bytes per frame
2966 size_t bpf = audio_bytes_per_sample(out->format) *
2967 audio_channel_count_from_out_mask(out->channel_mask);
2968 if (bpf != 0)
2969 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302970 ALOGD(" %s: sound card is not active/SSR state", __func__);
2971 ret= -EIO;
2972 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302973 }
2974 }
2975
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302976 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302977 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2978 if (audio_bytes_per_sample(out->format) != 0)
2979 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2980 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302981 goto exit;
2982 }
2983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002985 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002986 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002987 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2988 ret = voice_extn_compress_voip_start_output_stream(out);
2989 else
2990 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002991 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002994 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 goto exit;
2996 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002997
2998 if (last_known_cal_step != -1) {
2999 ALOGD("%s: retry previous failed cal level set", __func__);
3000 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003
Ashish Jain81eb2a82015-05-13 10:52:34 +05303004 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003005 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303006 adev->is_channel_status_set = true;
3007 }
3008
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003009 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003010 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003011 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003012 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003013 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3014 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303015 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3016 ALOGD("copl(%p):send next track params in gapless", out);
3017 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3018 out->send_next_track_params = false;
3019 out->is_compr_metadata_avail = false;
3020 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003021 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303022 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303023 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003024
Ashish Jain83a6cc22016-06-28 14:34:17 +05303025 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303026 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303027 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303028 pthread_mutex_unlock(&out->lock);
3029 return -EINVAL;
3030 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303031 audio_format_t dst_format = out->hal_op_format;
3032 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303033
3034 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3035 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3036
Ashish Jain83a6cc22016-06-28 14:34:17 +05303037 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303038 dst_format,
3039 buffer,
3040 src_format,
3041 frames);
3042
Ashish Jain83a6cc22016-06-28 14:34:17 +05303043 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303044 bytes_to_write);
3045
3046 /*Convert written bytes in audio flinger format*/
3047 if (ret > 0)
3048 ret = ((ret * format_to_bitwidth_table[out->format]) /
3049 format_to_bitwidth_table[dst_format]);
3050 }
3051 } else
3052 ret = compress_write(out->compr, buffer, bytes);
3053
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303054 if (ret < 0)
3055 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303056 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303057 /*msg to cb thread only if non blocking write is enabled*/
3058 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303059 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303061 } else if (-ENETRESET == ret) {
3062 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3063 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3064 pthread_mutex_unlock(&out->lock);
3065 out_standby(&out->stream.common);
3066 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 }
Ashish Jain5106d362016-05-11 19:23:33 +05303068 if ( ret == (ssize_t)bytes && !out->non_blocking)
3069 out->written += bytes;
3070
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303071 /* Call compr start only when non-zero bytes of data is there to be rendered */
3072 if (!out->playback_started && ret > 0) {
3073 int status = compress_start(out->compr);
3074 if (status < 0) {
3075 ret = status;
3076 ALOGE("%s: compr start failed with err %d", __func__, errno);
3077 goto exit;
3078 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003079 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 out->playback_started = 1;
3081 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003082
3083 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3084 popcount(out->channel_mask),
3085 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 }
3087 pthread_mutex_unlock(&out->lock);
3088 return ret;
3089 } else {
3090 if (out->pcm) {
3091 if (out->muted)
3092 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003093
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303094 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003095
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003096 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003097
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003098 if (out->config.rate)
3099 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3100 out->config.rate;
3101
3102 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3103
3104 request_out_focus(out, ns);
3105
3106 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003107 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003108 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303109 out->convert_buffer != NULL) {
3110
3111 memcpy_by_audio_format(out->convert_buffer,
3112 out->hal_op_format,
3113 buffer,
3114 out->hal_ip_format,
3115 out->config.period_size * out->config.channels);
3116
3117 ret = pcm_write(out->pcm, out->convert_buffer,
3118 (out->config.period_size *
3119 out->config.channels *
3120 format_to_bitwidth_table[out->hal_op_format]));
3121 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003122 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303123 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003124
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003125 release_out_focus(out);
3126
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303127 if (ret < 0)
3128 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303129 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3130 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3131 else
3132 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 }
3135
3136exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303137 /* ToDo: There may be a corner case when SSR happens back to back during
3138 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303139 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303140 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303141 }
3142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 pthread_mutex_unlock(&out->lock);
3144
3145 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003146 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003147 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303148 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303149 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303150 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303151 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303152 out->standby = true;
3153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303155 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3156 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3157 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 }
3159 return bytes;
3160}
3161
3162static int out_get_render_position(const struct audio_stream_out *stream,
3163 uint32_t *dsp_frames)
3164{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003165 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303166 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003167
3168 if (dsp_frames == NULL)
3169 return -EINVAL;
3170
3171 *dsp_frames = 0;
3172 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003173 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303174
3175 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3176 * this operation and adev_close_output_stream(where out gets reset).
3177 */
3178 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3179 *dsp_frames = get_actual_pcm_frames_rendered(out);
3180 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3181 return 0;
3182 }
3183
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003184 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303185 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303186 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303188 if (ret < 0)
3189 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303191 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 }
3193 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303194 if (-ENETRESET == ret) {
3195 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3196 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3197 return -EINVAL;
3198 } else if(ret < 0) {
3199 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3200 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303201 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3202 /*
3203 * Handle corner case where compress session is closed during SSR
3204 * and timestamp is queried
3205 */
3206 ALOGE(" ERROR: sound card not active, return error");
3207 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303208 } else {
3209 return 0;
3210 }
Zhou Song32a556e2015-05-05 10:46:56 +08003211 } else if (audio_is_linear_pcm(out->format)) {
3212 *dsp_frames = out->written;
3213 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 } else
3215 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216}
3217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003218static int out_add_audio_effect(const struct audio_stream *stream __unused,
3219 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220{
3221 return 0;
3222}
3223
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003224static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3225 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226{
3227 return 0;
3228}
3229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003230static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3231 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232{
3233 return -EINVAL;
3234}
3235
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003236static int out_get_presentation_position(const struct audio_stream_out *stream,
3237 uint64_t *frames, struct timespec *timestamp)
3238{
3239 struct stream_out *out = (struct stream_out *)stream;
3240 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003241 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003242
Ashish Jain5106d362016-05-11 19:23:33 +05303243 /* below piece of code is not guarded against any lock because audioFliner serializes
3244 * this operation and adev_close_output_stream( where out gets reset).
3245 */
3246 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3247 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3248 *frames = get_actual_pcm_frames_rendered(out);
3249 /* this is the best we can do */
3250 clock_gettime(CLOCK_MONOTONIC, timestamp);
3251 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3252 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3253 return 0;
3254 }
3255
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003256 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003257
Ashish Jain5106d362016-05-11 19:23:33 +05303258 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3259 ret = compress_get_tstamp(out->compr, &dsp_frames,
3260 &out->sample_rate);
3261 ALOGVV("%s rendered frames %ld sample_rate %d",
3262 __func__, dsp_frames, out->sample_rate);
3263 *frames = dsp_frames;
3264 if (ret < 0)
3265 ret = -errno;
3266 if (-ENETRESET == ret) {
3267 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3268 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3269 ret = -EINVAL;
3270 } else
3271 ret = 0;
3272 /* this is the best we can do */
3273 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003274 } else {
3275 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003276 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003277 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3278 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003279 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003280 // This adjustment accounts for buffering after app processor.
3281 // It is based on estimated DSP latency per use case, rather than exact.
3282 signed_frames -=
3283 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3284
Eric Laurent949a0892013-09-20 09:20:13 -07003285 // It would be unusual for this value to be negative, but check just in case ...
3286 if (signed_frames >= 0) {
3287 *frames = signed_frames;
3288 ret = 0;
3289 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003290 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303291 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3292 *frames = out->written;
3293 clock_gettime(CLOCK_MONOTONIC, timestamp);
3294 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003295 }
3296 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003297 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003298 return ret;
3299}
3300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301static int out_set_callback(struct audio_stream_out *stream,
3302 stream_callback_t callback, void *cookie)
3303{
3304 struct stream_out *out = (struct stream_out *)stream;
3305
3306 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003307 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 out->offload_callback = callback;
3309 out->offload_cookie = cookie;
3310 pthread_mutex_unlock(&out->lock);
3311 return 0;
3312}
3313
3314static int out_pause(struct audio_stream_out* stream)
3315{
3316 struct stream_out *out = (struct stream_out *)stream;
3317 int status = -ENOSYS;
3318 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003319 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003320 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003321 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003322 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303323 struct audio_device *adev = out->dev;
3324 int snd_scard_state = get_snd_card_state(adev);
3325
3326 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3327 status = compress_pause(out->compr);
3328
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003329 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003330
Mingming Yin21854652016-04-13 11:54:02 -07003331 if (audio_extn_passthru_is_active()) {
3332 ALOGV("offload use case, pause passthru");
3333 audio_extn_passthru_on_pause(out);
3334 }
3335
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303336 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003337 audio_extn_dts_notify_playback_state(out->usecase, 0,
3338 out->sample_rate, popcount(out->channel_mask),
3339 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 }
3341 pthread_mutex_unlock(&out->lock);
3342 }
3343 return status;
3344}
3345
3346static int out_resume(struct audio_stream_out* stream)
3347{
3348 struct stream_out *out = (struct stream_out *)stream;
3349 int status = -ENOSYS;
3350 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003352 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003354 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303356 struct audio_device *adev = out->dev;
3357 int snd_scard_state = get_snd_card_state(adev);
3358
Mingming Yin21854652016-04-13 11:54:02 -07003359 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3360 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3361 pthread_mutex_lock(&out->dev->lock);
3362 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003363 pthread_mutex_unlock(&out->dev->lock);
3364 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303365 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003366 }
3367 if (!status) {
3368 out->offload_state = OFFLOAD_STATE_PLAYING;
3369 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303370 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003371 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3372 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 }
3374 pthread_mutex_unlock(&out->lock);
3375 }
3376 return status;
3377}
3378
3379static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3380{
3381 struct stream_out *out = (struct stream_out *)stream;
3382 int status = -ENOSYS;
3383 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003384 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003385 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3387 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3388 else
3389 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3390 pthread_mutex_unlock(&out->lock);
3391 }
3392 return status;
3393}
3394
3395static int out_flush(struct audio_stream_out* stream)
3396{
3397 struct stream_out *out = (struct stream_out *)stream;
3398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003400 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003401 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003402 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3403 stop_compressed_output_l(out);
3404 out->written = 0;
3405 } else {
3406 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3407 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003408 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003409 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003410 return 0;
3411 }
3412 return -ENOSYS;
3413}
3414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415/** audio_stream_in implementation **/
3416static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3417{
3418 struct stream_in *in = (struct stream_in *)stream;
3419
3420 return in->config.rate;
3421}
3422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003423static int in_set_sample_rate(struct audio_stream *stream __unused,
3424 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425{
3426 return -ENOSYS;
3427}
3428
3429static size_t in_get_buffer_size(const struct audio_stream *stream)
3430{
3431 struct stream_in *in = (struct stream_in *)stream;
3432
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003433 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3434 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003435 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3436 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303437 else if(audio_extn_cin_attached_usecase(in->usecase))
3438 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003439
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003440 return in->config.period_size * in->af_period_multiplier *
3441 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442}
3443
3444static uint32_t in_get_channels(const struct audio_stream *stream)
3445{
3446 struct stream_in *in = (struct stream_in *)stream;
3447
3448 return in->channel_mask;
3449}
3450
3451static audio_format_t in_get_format(const struct audio_stream *stream)
3452{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003453 struct stream_in *in = (struct stream_in *)stream;
3454
3455 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456}
3457
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003458static int in_set_format(struct audio_stream *stream __unused,
3459 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460{
3461 return -ENOSYS;
3462}
3463
3464static int in_standby(struct audio_stream *stream)
3465{
3466 struct stream_in *in = (struct stream_in *)stream;
3467 struct audio_device *adev = in->dev;
3468 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303469 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3470 stream, in->usecase, use_case_table[in->usecase]);
3471
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003472 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003473 if (!in->standby && in->is_st_session) {
3474 ALOGD("%s: sound trigger pcm stop lab", __func__);
3475 audio_extn_sound_trigger_stop_lab(in);
3476 in->standby = 1;
3477 }
3478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003480 if (adev->adm_deregister_stream)
3481 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3482
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003483 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003485 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3486 voice_extn_compress_voip_close_input_stream(stream);
3487 ALOGD("VOIP input entered standby");
3488 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303489 if (audio_extn_cin_attached_usecase(in->usecase))
3490 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003491 if (in->pcm) {
3492 pcm_close(in->pcm);
3493 in->pcm = NULL;
3494 }
3495 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003496 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003497 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 }
3499 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003500 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 return status;
3502}
3503
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003504static int in_dump(const struct audio_stream *stream __unused,
3505 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506{
3507 return 0;
3508}
3509
3510static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3511{
3512 struct stream_in *in = (struct stream_in *)stream;
3513 struct audio_device *adev = in->dev;
3514 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003516 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303518 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 parms = str_parms_create_str(kvpairs);
3520
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303521 if (!parms)
3522 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003523 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003524 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003525
3526 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3527 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 val = atoi(value);
3529 /* no audio source uses val == 0 */
3530 if ((in->source != val) && (val != 0)) {
3531 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003532 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3533 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3534 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003535 (in->config.rate == 8000 || in->config.rate == 16000 ||
3536 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003537 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003538 err = voice_extn_compress_voip_open_input_stream(in);
3539 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003540 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003541 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003542 }
3543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544 }
3545 }
3546
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003547 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3548 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003550 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551 in->device = val;
3552 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003553 if (!in->standby && !in->is_st_session) {
3554 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003555 if (adev->adm_on_routing_change)
3556 adev->adm_on_routing_change(adev->adm_data,
3557 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003558 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 }
3561 }
3562
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303563 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3564 if (err >= 0) {
3565 strlcpy(in->profile, value, sizeof(in->profile));
3566 ALOGV("updating stream profile with value '%s'", in->profile);
3567 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3568 &adev->streams_input_cfg_list,
3569 in->device, in->flags, in->format,
3570 in->sample_rate, in->bit_width,
3571 in->profile, &in->app_type_cfg);
3572 }
3573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003575 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576
3577 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303578error:
Eric Laurent994a6932013-07-17 11:51:42 -07003579 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 return ret;
3581}
3582
3583static char* in_get_parameters(const struct audio_stream *stream,
3584 const char *keys)
3585{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003586 struct stream_in *in = (struct stream_in *)stream;
3587 struct str_parms *query = str_parms_create_str(keys);
3588 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003589 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003590
3591 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003592 if (reply) {
3593 str_parms_destroy(reply);
3594 }
3595 if (query) {
3596 str_parms_destroy(query);
3597 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003598 ALOGE("in_get_parameters: failed to create query or reply");
3599 return NULL;
3600 }
3601
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003602 ALOGV("%s: enter: keys - %s", __func__, keys);
3603
3604 voice_extn_in_get_parameters(in, query, reply);
3605
3606 str = str_parms_to_str(reply);
3607 str_parms_destroy(query);
3608 str_parms_destroy(reply);
3609
3610 ALOGV("%s: exit: returns - %s", __func__, str);
3611 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003614static int in_set_gain(struct audio_stream_in *stream __unused,
3615 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616{
3617 return 0;
3618}
3619
3620static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3621 size_t bytes)
3622{
3623 struct stream_in *in = (struct stream_in *)stream;
3624 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303625 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303626 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303627 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003629 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303630
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003631 if (in->is_st_session) {
3632 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3633 /* Read from sound trigger HAL */
3634 audio_extn_sound_trigger_read(in, buffer, bytes);
3635 pthread_mutex_unlock(&in->lock);
3636 return bytes;
3637 }
3638
Ashish Jainbbce4322016-02-16 13:25:27 +05303639 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003640 ALOGD(" %s: sound card is not active/SSR state", __func__);
3641 ret= -EIO;;
3642 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303643 }
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003646 pthread_mutex_lock(&adev->lock);
3647 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3648 ret = voice_extn_compress_voip_start_input_stream(in);
3649 else
3650 ret = start_input_stream(in);
3651 pthread_mutex_unlock(&adev->lock);
3652 if (ret != 0) {
3653 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 }
3655 in->standby = 0;
3656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003658 // what's the duration requested by the client?
3659 long ns = 0;
3660
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303661 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003662 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3663 in->config.rate;
3664
3665 request_in_focus(in, ns);
3666 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003667
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303668 if (audio_extn_cin_attached_usecase(in->usecase)) {
3669 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3670 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303671 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003672 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303673 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003674 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003675 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003676 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303677 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003678 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303679 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3680 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3681 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3682 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303683 ret = -EINVAL;
3684 goto exit;
3685 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303686 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303687 ret = -errno;
3688 }
3689 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303690 /* bytes read is always set to bytes for non compress usecases */
3691 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 }
3693
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003694 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 /*
3697 * Instead of writing zeroes here, we could trust the hardware
3698 * to always provide zeroes when muted.
3699 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303700 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3701 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 memset(buffer, 0, bytes);
3703
3704exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303705 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303706 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003707 if (-ENETRESET == ret)
3708 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 pthread_mutex_unlock(&in->lock);
3711
3712 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303713 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303714 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303715 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303716 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303717 in->standby = true;
3718 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303719 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003721 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303722 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303723 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303725 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726}
3727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003728static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729{
3730 return 0;
3731}
3732
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003733static int add_remove_audio_effect(const struct audio_stream *stream,
3734 effect_handle_t effect,
3735 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003737 struct stream_in *in = (struct stream_in *)stream;
3738 int status = 0;
3739 effect_descriptor_t desc;
3740
3741 status = (*effect)->get_descriptor(effect, &desc);
3742 if (status != 0)
3743 return status;
3744
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003745 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003746 pthread_mutex_lock(&in->dev->lock);
3747 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3748 in->enable_aec != enable &&
3749 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3750 in->enable_aec = enable;
3751 if (!in->standby)
3752 select_devices(in->dev, in->usecase);
3753 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003754 if (in->enable_ns != enable &&
3755 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3756 in->enable_ns = enable;
3757 if (!in->standby)
3758 select_devices(in->dev, in->usecase);
3759 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003760 pthread_mutex_unlock(&in->dev->lock);
3761 pthread_mutex_unlock(&in->lock);
3762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 return 0;
3764}
3765
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003766static int in_add_audio_effect(const struct audio_stream *stream,
3767 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768{
Eric Laurent994a6932013-07-17 11:51:42 -07003769 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003770 return add_remove_audio_effect(stream, effect, true);
3771}
3772
3773static int in_remove_audio_effect(const struct audio_stream *stream,
3774 effect_handle_t effect)
3775{
Eric Laurent994a6932013-07-17 11:51:42 -07003776 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003777 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778}
3779
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303780int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 audio_io_handle_t handle,
3782 audio_devices_t devices,
3783 audio_output_flags_t flags,
3784 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003785 struct audio_stream_out **stream_out,
3786 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787{
3788 struct audio_device *adev = (struct audio_device *)dev;
3789 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303790 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003791 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303794
3795 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3796 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003797 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303798 return -EINVAL;
3799 }
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3802
Mingming Yin3a941d42016-02-17 18:08:05 -08003803 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3804 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303805 devices, flags, &out->stream);
3806
3807
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003808 if (!out) {
3809 return -ENOMEM;
3810 }
3811
Haynes Mathew George204045b2015-02-25 20:32:03 -08003812 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003813 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003814 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 if (devices == AUDIO_DEVICE_NONE)
3817 devices = AUDIO_DEVICE_OUT_SPEAKER;
3818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 out->flags = flags;
3820 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003821 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003822 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003823 out->sample_rate = config->sample_rate;
3824 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3825 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003826 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003827 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003828 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303829 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830
Mingming Yin3a941d42016-02-17 18:08:05 -08003831 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3832 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3833 pthread_mutex_lock(&adev->lock);
3834 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3835 ret = read_hdmi_sink_caps(out);
3836 pthread_mutex_unlock(&adev->lock);
3837 if (ret != 0) {
3838 if (ret == -ENOSYS) {
3839 /* ignore and go with default */
3840 ret = 0;
3841 } else {
3842 ALOGE("error reading hdmi sink caps");
3843 goto error_open;
3844 }
3845 }
3846 }
3847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003849 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303850 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3851 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003852 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3853 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3854
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003855 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003856 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3857 /*
3858 * Do not handle stereo output in Multi-channel cases
3859 * Stereo case is handled in normal playback path
3860 */
3861 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3862 ret = AUDIO_CHANNEL_OUT_STEREO;
3863 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003864
3865 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3866 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003867 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003868 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003869 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003870
3871 if (config->sample_rate == 0)
3872 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3873 if (config->channel_mask == 0)
3874 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003875 if (config->format == 0)
3876 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003877
3878 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003879 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003880 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3882 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003884 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003886 } 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 -08003887 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003888 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003889 ret = voice_extn_compress_voip_open_output_stream(out);
3890 if (ret != 0) {
3891 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3892 __func__, ret);
3893 goto error_open;
3894 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003895 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3896 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003898 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3899 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3900 ALOGE("%s: Unsupported Offload information", __func__);
3901 ret = -EINVAL;
3902 goto error_open;
3903 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003904
Mingming Yin3a941d42016-02-17 18:08:05 -08003905 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003906 if(config->offload_info.format == 0)
3907 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003908 if (config->offload_info.sample_rate == 0)
3909 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003910 }
3911
Mingming Yin90310102013-11-13 16:57:00 -08003912 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303913 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003914 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003915 ret = -EINVAL;
3916 goto error_open;
3917 }
3918
3919 out->compr_config.codec = (struct snd_codec *)
3920 calloc(1, sizeof(struct snd_codec));
3921
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003922 if (!out->compr_config.codec) {
3923 ret = -ENOMEM;
3924 goto error_open;
3925 }
3926
vivek mehta0ea887a2015-08-26 14:01:20 -07003927 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303928 out->stream.pause = out_pause;
3929 out->stream.flush = out_flush;
3930 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003931 out->usecase = get_offload_usecase(adev, true);
3932 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003933 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003934 out->stream.set_callback = out_set_callback;
3935 out->stream.pause = out_pause;
3936 out->stream.resume = out_resume;
3937 out->stream.drain = out_drain;
3938 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003939 out->usecase = get_offload_usecase(adev, false);
3940 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003941 }
vivek mehta446c3962015-09-14 10:57:35 -07003942
3943 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003944 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3945 config->format == 0 && config->sample_rate == 0 &&
3946 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003947 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003948 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3949 } else {
3950 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3951 ret = -EEXIST;
3952 goto error_open;
3953 }
vivek mehta446c3962015-09-14 10:57:35 -07003954 }
3955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003956 if (config->offload_info.channel_mask)
3957 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003958 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003960 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003961 } else {
3962 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3963 ret = -EINVAL;
3964 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003965 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003966
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003967 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003968 out->sample_rate = config->offload_info.sample_rate;
3969
Mingming Yin3ee55c62014-08-04 14:23:35 -07003970 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003971
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303972 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3973 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3974 audio_extn_dolby_send_ddp_endp_params(adev);
3975 audio_extn_dolby_set_dmid(adev);
3976 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003979 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003980 out->compr_config.codec->bit_rate =
3981 config->offload_info.bit_rate;
3982 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303983 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303985 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003986 /*TODO: Do we need to change it for passthrough */
3987 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003988
Manish Dewangana6fc5442015-08-24 20:30:31 +05303989 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3990 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3991 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3992 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303993
3994 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3995 AUDIO_FORMAT_PCM) {
3996
3997 /*Based on platform support, configure appropriate alsa format for corresponding
3998 *hal input format.
3999 */
4000 out->compr_config.codec->format = hal_format_to_alsa(
4001 config->offload_info.format);
4002
Ashish Jain83a6cc22016-06-28 14:34:17 +05304003 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304004 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304005 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304006
4007 /*for direct PCM playback populate bit_width based on selected alsa format as
4008 *hal input format and alsa format might differ based on platform support.
4009 */
4010 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304011 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304012
4013 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4014
4015 /* Check if alsa session is configured with the same format as HAL input format,
4016 * if not then derive correct fragment size needed to accomodate the
4017 * conversion of HAL input format to alsa format.
4018 */
4019 audio_extn_utils_update_direct_pcm_fragment_size(out);
4020
4021 /*if hal input and output fragment size is different this indicates HAL input format is
4022 *not same as the alsa format
4023 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304024 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304025 /*Allocate a buffer to convert input data to the alsa configured format.
4026 *size of convert buffer is equal to the size required to hold one fragment size
4027 *worth of pcm data, this is because flinger does not write more than fragment_size
4028 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304029 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4030 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304031 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4032 ret = -ENOMEM;
4033 goto error_open;
4034 }
4035 }
4036 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4037 out->compr_config.fragment_size =
4038 audio_extn_passthru_get_buffer_size(&config->offload_info);
4039 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4040 } else {
4041 out->compr_config.fragment_size =
4042 platform_get_compress_offload_buffer_size(&config->offload_info);
4043 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4044 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004045
Amit Shekhar6f461b12014-08-01 14:52:58 -07004046 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304047 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004048
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004049 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4050 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004051
Alexy Josephaa54c872014-12-03 02:46:47 -08004052
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004053 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304054 out->send_next_track_params = false;
4055 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004056 out->offload_state = OFFLOAD_STATE_IDLE;
4057 out->playback_started = 0;
4058
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004059 audio_extn_dts_create_state_notifier_node(out->usecase);
4060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4062 __func__, config->offload_info.version,
4063 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304064
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304065 /* Check if DSD audio format is supported in codec
4066 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304067 */
4068
4069 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304070 (!platform_check_codec_dsd_support(adev->platform) ||
4071 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304072 ret = -EINVAL;
4073 goto error_open;
4074 }
4075
Ashish Jain5106d362016-05-11 19:23:33 +05304076 /* Disable gapless if any of the following is true
4077 * passthrough playback
4078 * AV playback
4079 * Direct PCM playback
4080 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304081 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304082 (config->format == AUDIO_FORMAT_DSD) ||
4083 config->offload_info.has_video ||
4084 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304085 check_and_set_gapless_mode(adev, false);
4086 } else
4087 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004088
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304089 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004090 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4091 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304092 if (config->format == AUDIO_FORMAT_DSD) {
4093 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4094 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4095 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004096
4097 create_offload_callback_thread(out);
4098
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004099 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304100 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004101 if (ret != 0) {
4102 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4103 __func__, ret);
4104 goto error_open;
4105 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004106 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4107 if (config->sample_rate == 0)
4108 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4109 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4110 config->sample_rate != 8000) {
4111 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4112 ret = -EINVAL;
4113 goto error_open;
4114 }
4115 out->sample_rate = config->sample_rate;
4116 out->config.rate = config->sample_rate;
4117 if (config->format == AUDIO_FORMAT_DEFAULT)
4118 config->format = AUDIO_FORMAT_PCM_16_BIT;
4119 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4120 config->format = AUDIO_FORMAT_PCM_16_BIT;
4121 ret = -EINVAL;
4122 goto error_open;
4123 }
4124 out->format = config->format;
4125 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4126 out->config = pcm_config_afe_proxy_playback;
4127 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004128 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304129 unsigned int channels = 0;
4130 /*Update config params to default if not set by the caller*/
4131 if (config->sample_rate == 0)
4132 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4133 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4134 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4135 if (config->format == AUDIO_FORMAT_DEFAULT)
4136 config->format = AUDIO_FORMAT_PCM_16_BIT;
4137
4138 channels = audio_channel_count_from_out_mask(out->channel_mask);
4139
Ashish Jain83a6cc22016-06-28 14:34:17 +05304140 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4141 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004142 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4143 out->flags);
4144 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304145 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4146 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4147 out->config = pcm_config_low_latency;
4148 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4149 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4150 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304151 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4152 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4153 if (out->config.period_size <= 0) {
4154 ALOGE("Invalid configuration period size is not valid");
4155 ret = -EINVAL;
4156 goto error_open;
4157 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304158 } else {
4159 /* primary path is the default path selected if no other outputs are available/suitable */
4160 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4161 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4162 }
4163 out->hal_ip_format = format = out->format;
4164 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4165 out->hal_op_format = pcm_format_to_hal(out->config.format);
4166 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4167 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004168 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304169 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304170 if (out->hal_ip_format != out->hal_op_format) {
4171 uint32_t buffer_size = out->config.period_size *
4172 format_to_bitwidth_table[out->hal_op_format] *
4173 out->config.channels;
4174 out->convert_buffer = calloc(1, buffer_size);
4175 if (out->convert_buffer == NULL){
4176 ALOGE("Allocation failed for convert buffer for size %d",
4177 out->compr_config.fragment_size);
4178 ret = -ENOMEM;
4179 goto error_open;
4180 }
4181 ALOGD("Convert buffer allocated of size %d", buffer_size);
4182 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 }
4184
Ashish Jain83a6cc22016-06-28 14:34:17 +05304185 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4186 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4187
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004188 /* TODO remove this hardcoding and check why width is zero*/
4189 if (out->bit_width == 0)
4190 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304191 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004192 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004193 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304194 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304195 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004196 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4197 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4198 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004199 if(adev->primary_output == NULL)
4200 adev->primary_output = out;
4201 else {
4202 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004203 ret = -EEXIST;
4204 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004205 }
4206 }
4207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208 /* Check if this usecase is already existing */
4209 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004210 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4211 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004214 ret = -EEXIST;
4215 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 }
4217 pthread_mutex_unlock(&adev->lock);
4218
4219 out->stream.common.get_sample_rate = out_get_sample_rate;
4220 out->stream.common.set_sample_rate = out_set_sample_rate;
4221 out->stream.common.get_buffer_size = out_get_buffer_size;
4222 out->stream.common.get_channels = out_get_channels;
4223 out->stream.common.get_format = out_get_format;
4224 out->stream.common.set_format = out_set_format;
4225 out->stream.common.standby = out_standby;
4226 out->stream.common.dump = out_dump;
4227 out->stream.common.set_parameters = out_set_parameters;
4228 out->stream.common.get_parameters = out_get_parameters;
4229 out->stream.common.add_audio_effect = out_add_audio_effect;
4230 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4231 out->stream.get_latency = out_get_latency;
4232 out->stream.set_volume = out_set_volume;
4233 out->stream.write = out_write;
4234 out->stream.get_render_position = out_get_render_position;
4235 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004236 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004238 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004240 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004241 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242
4243 config->format = out->stream.common.get_format(&out->stream.common);
4244 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4245 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4246
4247 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304248 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004249 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004250
4251 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4252 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4253 popcount(out->channel_mask), out->playback_started);
4254
Eric Laurent994a6932013-07-17 11:51:42 -07004255 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004257
4258error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304259 if (out->convert_buffer)
4260 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004261 free(out);
4262 *stream_out = NULL;
4263 ALOGD("%s: exit: ret %d", __func__, ret);
4264 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265}
4266
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304267void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268 struct audio_stream_out *stream)
4269{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004270 struct stream_out *out = (struct stream_out *)stream;
4271 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004272 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004273
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304274 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4275
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004276 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304277 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004278 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304279 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004280 if(ret != 0)
4281 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4282 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004283 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004284 out_standby(&stream->common);
4285
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004286 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004287 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004288 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004289 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004290 if (out->compr_config.codec != NULL)
4291 free(out->compr_config.codec);
4292 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004293
Ashish Jain83a6cc22016-06-28 14:34:17 +05304294 if (out->convert_buffer != NULL) {
4295 free(out->convert_buffer);
4296 out->convert_buffer = NULL;
4297 }
4298
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004299 if (adev->voice_tx_output == out)
4300 adev->voice_tx_output = NULL;
4301
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004302 pthread_cond_destroy(&out->cond);
4303 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004305 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306}
4307
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004308static void close_compress_sessions(struct audio_device *adev)
4309{
Mingming Yin7b762e72015-03-04 13:47:32 -08004310 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304311 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004312 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004313 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304314
4315 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004316 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304317 if (is_offload_usecase(usecase->id)) {
4318 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004319 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4320 out = usecase->stream.out;
4321 pthread_mutex_unlock(&adev->lock);
4322 out_standby(&out->stream.common);
4323 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004324 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004325 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304326 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004327 }
4328 pthread_mutex_unlock(&adev->lock);
4329}
4330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4332{
4333 struct audio_device *adev = (struct audio_device *)dev;
4334 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004336 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004337 int ret;
4338 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004340 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304343 if (!parms)
4344 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004345 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4346 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304347 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304348 if (strstr(snd_card_status, "OFFLINE")) {
4349 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304350 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004351 //close compress sessions on OFFLINE status
4352 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304353 } else if (strstr(snd_card_status, "ONLINE")) {
4354 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304355 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004356 //send dts hpx license if enabled
4357 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304358 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304359 }
4360
4361 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004362 status = voice_set_parameters(adev, parms);
4363 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004364 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004366 status = platform_set_parameters(adev->platform, parms);
4367 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004368 goto done;
4369
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004370 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4371 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004372 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4374 adev->bluetooth_nrec = true;
4375 else
4376 adev->bluetooth_nrec = false;
4377 }
4378
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004379 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4380 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4382 adev->screen_off = false;
4383 else
4384 adev->screen_off = true;
4385 }
4386
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004387 ret = str_parms_get_int(parms, "rotation", &val);
4388 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004389 bool reverse_speakers = false;
4390 switch(val) {
4391 // FIXME: note that the code below assumes that the speakers are in the correct placement
4392 // relative to the user when the device is rotated 90deg from its default rotation. This
4393 // assumption is device-specific, not platform-specific like this code.
4394 case 270:
4395 reverse_speakers = true;
4396 break;
4397 case 0:
4398 case 90:
4399 case 180:
4400 break;
4401 default:
4402 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004403 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004404 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004405 if (status == 0) {
4406 if (adev->speaker_lr_swap != reverse_speakers) {
4407 adev->speaker_lr_swap = reverse_speakers;
4408 // only update the selected device if there is active pcm playback
4409 struct audio_usecase *usecase;
4410 struct listnode *node;
4411 list_for_each(node, &adev->usecase_list) {
4412 usecase = node_to_item(node, struct audio_usecase, list);
4413 if (usecase->type == PCM_PLAYBACK) {
4414 select_devices(adev, usecase->id);
4415 break;
4416 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004417 }
4418 }
4419 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004420 }
4421
Mingming Yin514a8bc2014-07-29 15:22:21 -07004422 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4423 if (ret >= 0) {
4424 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4425 adev->bt_wb_speech_enabled = true;
4426 else
4427 adev->bt_wb_speech_enabled = false;
4428 }
4429
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004430 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4431 if (ret >= 0) {
4432 val = atoi(value);
4433 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004434 ALOGV("cache new ext disp type and edid");
4435 ret = platform_get_ext_disp_type(adev->platform);
4436 if (ret < 0) {
4437 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004438 status = ret;
4439 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004440 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004441 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004442 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004443 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004444 /*
4445 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4446 * Per AudioPolicyManager, USB device is higher priority than WFD.
4447 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4448 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4449 * starting voice call on USB
4450 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004451 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4452 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004453 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4454 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004455 }
vivek mehta344576a2016-04-12 18:56:03 -07004456 ALOGV("detected USB connect .. disable proxy");
4457 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004458 }
4459 }
4460
4461 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4462 if (ret >= 0) {
4463 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004464 /*
4465 * The HDMI / Displayport disconnect handling has been moved to
4466 * audio extension to ensure that its parameters are not
4467 * invalidated prior to updating sysfs of the disconnect event
4468 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4469 */
4470 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004471 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004472 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4473 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304474 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4475 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004476 }
vivek mehta344576a2016-04-12 18:56:03 -07004477 ALOGV("detected USB disconnect .. enable proxy");
4478 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004479 }
4480 }
4481
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304482 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4483 if (ret >= 0) {
4484 struct audio_usecase *usecase;
4485 struct listnode *node;
4486 list_for_each(node, &adev->usecase_list) {
4487 usecase = node_to_item(node, struct audio_usecase, list);
4488 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004489 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304490 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304491 lock_output_stream(usecase->stream.out);
4492 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304493 //force device switch to re configure encoder
4494 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304495 audio_extn_a2dp_set_handoff_mode(false);
4496 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304497 break;
4498 }
4499 }
4500 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304501 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004502done:
4503 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004504 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304505error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004506 ALOGV("%s: exit with code(%d)", __func__, status);
4507 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508}
4509
4510static char* adev_get_parameters(const struct audio_hw_device *dev,
4511 const char *keys)
4512{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004513 struct audio_device *adev = (struct audio_device *)dev;
4514 struct str_parms *reply = str_parms_create();
4515 struct str_parms *query = str_parms_create_str(keys);
4516 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304517 char value[256] = {0};
4518 int ret = 0;
4519
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004520 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004521 if (reply) {
4522 str_parms_destroy(reply);
4523 }
4524 if (query) {
4525 str_parms_destroy(query);
4526 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004527 ALOGE("adev_get_parameters: failed to create query or reply");
4528 return NULL;
4529 }
4530
Naresh Tannirud7205b62014-06-20 02:54:48 +05304531 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4532 sizeof(value));
4533 if (ret >=0) {
4534 int val = 1;
4535 pthread_mutex_lock(&adev->snd_card_status.lock);
4536 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4537 val = 0;
4538 pthread_mutex_unlock(&adev->snd_card_status.lock);
4539 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4540 goto exit;
4541 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004542
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004543 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004544 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004545 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004546 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304547 pthread_mutex_unlock(&adev->lock);
4548
Naresh Tannirud7205b62014-06-20 02:54:48 +05304549exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004550 str = str_parms_to_str(reply);
4551 str_parms_destroy(query);
4552 str_parms_destroy(reply);
4553
4554 ALOGV("%s: exit: returns - %s", __func__, str);
4555 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556}
4557
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004558static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559{
4560 return 0;
4561}
4562
4563static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4564{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004565 int ret;
4566 struct audio_device *adev = (struct audio_device *)dev;
4567 pthread_mutex_lock(&adev->lock);
4568 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004569 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004570 pthread_mutex_unlock(&adev->lock);
4571 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572}
4573
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004574static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4575 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576{
4577 return -ENOSYS;
4578}
4579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004580static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4581 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582{
4583 return -ENOSYS;
4584}
4585
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004586static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4587 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588{
4589 return -ENOSYS;
4590}
4591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004592static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4593 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594{
4595 return -ENOSYS;
4596}
4597
4598static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4599{
4600 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602 pthread_mutex_lock(&adev->lock);
4603 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004604 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004606 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004607 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004608 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004609 adev->current_call_output = NULL;
4610 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 }
4612 pthread_mutex_unlock(&adev->lock);
4613 return 0;
4614}
4615
4616static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4617{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004618 int ret;
4619
4620 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004621 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004622 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4623 pthread_mutex_unlock(&adev->lock);
4624
4625 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626}
4627
4628static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4629{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004630 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 return 0;
4632}
4633
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004634static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 const struct audio_config *config)
4636{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004637 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004639 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4640 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641}
4642
4643static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004644 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 audio_devices_t devices,
4646 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004647 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304648 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004649 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004650 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651{
4652 struct audio_device *adev = (struct audio_device *)dev;
4653 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004654 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004655 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004656 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304657 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304660 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4661 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664
4665 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004666
4667 if (!in) {
4668 ALOGE("failed to allocate input stream");
4669 return -ENOMEM;
4670 }
4671
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304672 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304673 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4674 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004675 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004676 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 in->stream.common.get_sample_rate = in_get_sample_rate;
4679 in->stream.common.set_sample_rate = in_set_sample_rate;
4680 in->stream.common.get_buffer_size = in_get_buffer_size;
4681 in->stream.common.get_channels = in_get_channels;
4682 in->stream.common.get_format = in_get_format;
4683 in->stream.common.set_format = in_set_format;
4684 in->stream.common.standby = in_standby;
4685 in->stream.common.dump = in_dump;
4686 in->stream.common.set_parameters = in_set_parameters;
4687 in->stream.common.get_parameters = in_get_parameters;
4688 in->stream.common.add_audio_effect = in_add_audio_effect;
4689 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4690 in->stream.set_gain = in_set_gain;
4691 in->stream.read = in_read;
4692 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4693
4694 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004695 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 in->standby = 1;
4698 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004699 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004700 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004702 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004703 if (in->realtime) {
4704 in->config = pcm_config_audio_capture_rt;
4705 in->sample_rate = in->config.rate;
4706 in->af_period_multiplier = af_period_multiplier;
4707 } else {
4708 in->config = pcm_config_audio_capture;
4709 in->config.rate = config->sample_rate;
4710 in->sample_rate = config->sample_rate;
4711 in->af_period_multiplier = 1;
4712 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304713 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304715 /* restrict 24 bit capture for unprocessed source only
4716 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4717 */
4718 if (config->format == AUDIO_FORMAT_DEFAULT) {
4719 config->format = AUDIO_FORMAT_PCM_16_BIT;
4720 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4721 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4722 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4723 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4724 bool ret_error = false;
4725 in->bit_width = 24;
4726 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4727 from HAL is 24_packed and 8_24
4728 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4729 24_packed return error indicating supported format is 24_packed
4730 *> In case of any other source requesting 24 bit or float return error
4731 indicating format supported is 16 bit only.
4732
4733 on error flinger will retry with supported format passed
4734 */
4735 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4736 (source != AUDIO_SOURCE_CAMCORDER)) {
4737 config->format = AUDIO_FORMAT_PCM_16_BIT;
4738 if (config->sample_rate > 48000)
4739 config->sample_rate = 48000;
4740 ret_error = true;
4741 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4742 in->config.format = PCM_FORMAT_S24_3LE;
4743 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4744 in->config.format = PCM_FORMAT_S24_LE;
4745 } else {
4746 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4747 ret_error = true;
4748 }
4749
4750 if (ret_error) {
4751 ret = -EINVAL;
4752 goto err_open;
4753 }
4754 }
4755
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304756 in->usecase = USECASE_AUDIO_RECORD;
4757 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4758 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4759 is_low_latency = true;
4760#if LOW_LATENCY_CAPTURE_USE_CASE
4761 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4762#endif
4763 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4764 }
4765
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304766 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304767 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4768 (adev->mode != AUDIO_MODE_IN_CALL)) {
4769 ret = -EINVAL;
4770 goto err_open;
4771 }
4772
4773 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4774 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004775 if (config->sample_rate == 0)
4776 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4777 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4778 config->sample_rate != 8000) {
4779 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4780 ret = -EINVAL;
4781 goto err_open;
4782 }
4783 if (config->format == AUDIO_FORMAT_DEFAULT)
4784 config->format = AUDIO_FORMAT_PCM_16_BIT;
4785 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4786 config->format = AUDIO_FORMAT_PCM_16_BIT;
4787 ret = -EINVAL;
4788 goto err_open;
4789 }
4790
4791 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4792 in->config = pcm_config_afe_proxy_record;
4793 in->config.channels = channel_count;
4794 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304795 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304796 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4797 in, config, &channel_mask_updated)) {
4798 if (channel_mask_updated == true) {
4799 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4800 __func__, config->channel_mask);
4801 ret = -EINVAL;
4802 goto err_open;
4803 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304804 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004805 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004806 audio_extn_compr_cap_format_supported(config->format) &&
4807 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004808 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304809 } else if (audio_extn_cin_applicable_stream(in)) {
4810 ret = audio_extn_cin_configure_input_stream(in);
4811 if (ret)
4812 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004813 } else {
4814 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004815 if (!in->realtime) {
4816 in->format = config->format;
4817 frame_size = audio_stream_in_frame_size(&in->stream);
4818 buffer_size = get_input_buffer_size(config->sample_rate,
4819 config->format,
4820 channel_count,
4821 is_low_latency);
4822 in->config.period_size = buffer_size / frame_size;
4823 }
4824
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004825 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004826 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004827 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004828 (in->config.rate == 8000 || in->config.rate == 16000 ||
4829 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004830 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4831 voice_extn_compress_voip_open_input_stream(in);
4832 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304835 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4836 &adev->streams_input_cfg_list,
4837 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304838 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304839
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004840 /* This stream could be for sound trigger lab,
4841 get sound trigger pcm if present */
4842 audio_extn_sound_trigger_check_and_get_session(in);
4843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004845 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004846 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847
4848err_open:
4849 free(in);
4850 *stream_in = NULL;
4851 return ret;
4852}
4853
4854static void adev_close_input_stream(struct audio_hw_device *dev,
4855 struct audio_stream_in *stream)
4856{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004857 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004858 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004859 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304860
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304861 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004862
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304863 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004864 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304865
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004866 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304867 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004868 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304869 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004870 if (ret != 0)
4871 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4872 __func__, ret);
4873 } else
4874 in_standby(&stream->common);
4875
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004876 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004877 audio_extn_ssr_deinit();
4878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304880 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004881 audio_extn_compr_cap_format_supported(in->config.format))
4882 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304883
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304884 if (audio_extn_cin_attached_usecase(in->usecase))
4885 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004886
Mingming Yinfd7607b2016-01-22 12:48:44 -08004887 if (in->is_st_session) {
4888 ALOGV("%s: sound trigger pcm stop lab", __func__);
4889 audio_extn_sound_trigger_stop_lab(in);
4890 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004891 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 return;
4893}
4894
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004895static int adev_dump(const audio_hw_device_t *device __unused,
4896 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897{
4898 return 0;
4899}
4900
4901static int adev_close(hw_device_t *device)
4902{
4903 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004904
4905 if (!adev)
4906 return 0;
4907
4908 pthread_mutex_lock(&adev_init_lock);
4909
4910 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004911 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004912 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304913 audio_extn_utils_release_streams_cfg_lists(
4914 &adev->streams_output_cfg_list,
4915 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304916 if (audio_extn_qaf_is_enabled())
4917 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004918 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004919 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004920 free(adev->snd_dev_ref_cnt);
4921 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004922 if (adev->adm_deinit)
4923 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304924 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004925 free(device);
4926 adev = NULL;
4927 }
4928 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 return 0;
4931}
4932
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004933/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4934 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4935 * just that it _might_ work.
4936 */
4937static int period_size_is_plausible_for_low_latency(int period_size)
4938{
4939 switch (period_size) {
4940 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004941 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004942 case 240:
4943 case 320:
4944 case 480:
4945 return 1;
4946 default:
4947 return 0;
4948 }
4949}
4950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004951static int adev_open(const hw_module_t *module, const char *name,
4952 hw_device_t **device)
4953{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304954 int ret;
4955
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004956 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4958
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004959 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004960 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004961 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004962 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004963 ALOGD("%s: returning existing instance of adev", __func__);
4964 ALOGD("%s: exit", __func__);
4965 pthread_mutex_unlock(&adev_init_lock);
4966 return 0;
4967 }
4968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004969 adev = calloc(1, sizeof(struct audio_device));
4970
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004971 if (!adev) {
4972 pthread_mutex_unlock(&adev_init_lock);
4973 return -ENOMEM;
4974 }
4975
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004976 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4979 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4980 adev->device.common.module = (struct hw_module_t *)module;
4981 adev->device.common.close = adev_close;
4982
4983 adev->device.init_check = adev_init_check;
4984 adev->device.set_voice_volume = adev_set_voice_volume;
4985 adev->device.set_master_volume = adev_set_master_volume;
4986 adev->device.get_master_volume = adev_get_master_volume;
4987 adev->device.set_master_mute = adev_set_master_mute;
4988 adev->device.get_master_mute = adev_get_master_mute;
4989 adev->device.set_mode = adev_set_mode;
4990 adev->device.set_mic_mute = adev_set_mic_mute;
4991 adev->device.get_mic_mute = adev_get_mic_mute;
4992 adev->device.set_parameters = adev_set_parameters;
4993 adev->device.get_parameters = adev_get_parameters;
4994 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4995 adev->device.open_output_stream = adev_open_output_stream;
4996 adev->device.close_output_stream = adev_close_output_stream;
4997 adev->device.open_input_stream = adev_open_input_stream;
4998 adev->device.close_input_stream = adev_close_input_stream;
4999 adev->device.dump = adev_dump;
5000
5001 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005003 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005004 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005007 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005008 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005009 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005010 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005011 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005012 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005013 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005014 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305015 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305016 adev->perf_lock_opts[0] = 0x101;
5017 adev->perf_lock_opts[1] = 0x20E;
5018 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305019
5020 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5021 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005023 adev->platform = platform_init(adev);
5024 if (!adev->platform) {
5025 free(adev->snd_dev_ref_cnt);
5026 free(adev);
5027 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5028 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005029 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305030 pthread_mutex_destroy(&adev->lock);
5031 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005032 return -EINVAL;
5033 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005034
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305035 if (audio_extn_qaf_is_enabled()) {
5036 ret = audio_extn_qaf_init(adev);
5037 if (ret < 0) {
5038 free(adev);
5039 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5040 *device = NULL;
5041 pthread_mutex_unlock(&adev_init_lock);
5042 pthread_mutex_destroy(&adev->lock);
5043 return ret;
5044 }
5045
5046 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5047 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5048 }
5049
Naresh Tanniru4c630392014-05-12 01:05:52 +05305050 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5051
Eric Laurentc4aef752013-09-12 17:45:53 -07005052 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5053 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5054 if (adev->visualizer_lib == NULL) {
5055 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5056 } else {
5057 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5058 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005059 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005060 "visualizer_hal_start_output");
5061 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005062 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005063 "visualizer_hal_stop_output");
5064 }
5065 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305066 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005067 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005068 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005069 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005070
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005071 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5072 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5073 if (adev->offload_effects_lib == NULL) {
5074 ALOGE("%s: DLOPEN failed for %s", __func__,
5075 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5076 } else {
5077 ALOGV("%s: DLOPEN successful for %s", __func__,
5078 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5079 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305080 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005081 "offload_effects_bundle_hal_start_output");
5082 adev->offload_effects_stop_output =
5083 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5084 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005085 adev->offload_effects_set_hpx_state =
5086 (int (*)(bool))dlsym(adev->offload_effects_lib,
5087 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305088 adev->offload_effects_get_parameters =
5089 (void (*)(struct str_parms *, struct str_parms *))
5090 dlsym(adev->offload_effects_lib,
5091 "offload_effects_bundle_get_parameters");
5092 adev->offload_effects_set_parameters =
5093 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5094 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005095 }
5096 }
5097
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005098 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5099 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5100 if (adev->adm_lib == NULL) {
5101 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5102 } else {
5103 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5104 adev->adm_init = (adm_init_t)
5105 dlsym(adev->adm_lib, "adm_init");
5106 adev->adm_deinit = (adm_deinit_t)
5107 dlsym(adev->adm_lib, "adm_deinit");
5108 adev->adm_register_input_stream = (adm_register_input_stream_t)
5109 dlsym(adev->adm_lib, "adm_register_input_stream");
5110 adev->adm_register_output_stream = (adm_register_output_stream_t)
5111 dlsym(adev->adm_lib, "adm_register_output_stream");
5112 adev->adm_deregister_stream = (adm_deregister_stream_t)
5113 dlsym(adev->adm_lib, "adm_deregister_stream");
5114 adev->adm_request_focus = (adm_request_focus_t)
5115 dlsym(adev->adm_lib, "adm_request_focus");
5116 adev->adm_abandon_focus = (adm_abandon_focus_t)
5117 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005118 adev->adm_set_config = (adm_set_config_t)
5119 dlsym(adev->adm_lib, "adm_set_config");
5120 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5121 dlsym(adev->adm_lib, "adm_request_focus_v2");
5122 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5123 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5124 adev->adm_on_routing_change = (adm_on_routing_change_t)
5125 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005126 }
5127 }
5128
Mingming Yin514a8bc2014-07-29 15:22:21 -07005129 adev->bt_wb_speech_enabled = false;
5130
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005131 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005132 *device = &adev->device.common;
5133
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305134 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5135 &adev->streams_output_cfg_list,
5136 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005137
Kiran Kandi910e1862013-10-29 13:29:42 -07005138 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005139
5140 char value[PROPERTY_VALUE_MAX];
5141 int trial;
5142 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5143 trial = atoi(value);
5144 if (period_size_is_plausible_for_low_latency(trial)) {
5145 pcm_config_low_latency.period_size = trial;
5146 pcm_config_low_latency.start_threshold = trial / 4;
5147 pcm_config_low_latency.avail_min = trial / 4;
5148 configured_low_latency_capture_period_size = trial;
5149 }
5150 }
5151 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5152 trial = atoi(value);
5153 if (period_size_is_plausible_for_low_latency(trial)) {
5154 configured_low_latency_capture_period_size = trial;
5155 }
5156 }
5157
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005158 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5159 af_period_multiplier = atoi(value);
5160 if (af_period_multiplier < 0)
5161 af_period_multiplier = 2;
5162 else if (af_period_multiplier > 4)
5163 af_period_multiplier = 4;
5164
5165 ALOGV("new period_multiplier = %d", af_period_multiplier);
5166 }
5167
vivek mehta446c3962015-09-14 10:57:35 -07005168 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005169 pthread_mutex_unlock(&adev_init_lock);
5170
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005171 if (adev->adm_init)
5172 adev->adm_data = adev->adm_init();
5173
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305174 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305175 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005176 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177 return 0;
5178}
5179
5180static struct hw_module_methods_t hal_module_methods = {
5181 .open = adev_open,
5182};
5183
5184struct audio_module HAL_MODULE_INFO_SYM = {
5185 .common = {
5186 .tag = HARDWARE_MODULE_TAG,
5187 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5188 .hal_api_version = HARDWARE_HAL_API_VERSION,
5189 .id = AUDIO_HARDWARE_MODULE_ID,
5190 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005191 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 .methods = &hal_module_methods,
5193 },
5194};