blob: 1b0e1f1991c59ae69c2dccf2553d49e1f2d928fd [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
609static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
610{
611 ALOGV("%s snd device %d", __func__, snd_device);
612 int new_backend_idx = platform_get_backend_index(snd_device);
613
614 if (((new_backend_idx == HEADPHONE_BACKEND) ||
615 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
616 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
617 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618 struct listnode *node = NULL;
619 struct audio_usecase *uc = NULL;
620 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Garmond Leung50058f62017-02-08 09:49:30 -0800622 int i, num_devices, ret = 0;
623 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530624
625 list_for_each(node, &adev->usecase_list) {
626 uc = node_to_item(node, struct audio_usecase, list);
627 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530628
Garmond Leung50058f62017-02-08 09:49:30 -0800629 if (curr_out && PCM_PLAYBACK == uc->type) {
630 ret = platform_split_snd_device(adev->platform,
631 uc->out_snd_device,
632 &num_devices,
633 split_snd_devices);
634 if (ret < 0 || num_devices == 0) {
635 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
636 split_snd_devices[0] = uc->out_snd_device;
637 num_devices = 1;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530638 }
Garmond Leung50058f62017-02-08 09:49:30 -0800639 for (i = 0; i < num_devices; i++) {
640 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
641 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
642 if((new_backend_idx == HEADPHONE_BACKEND) &&
643 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
644 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
645 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
646 __func__);
647 enable_asrc_mode(adev);
648 break;
649 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
650 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
651 (usecase_backend_idx == HEADPHONE_BACKEND)) {
652 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
653 __func__);
654 disable_audio_route(adev, uc);
655 disable_snd_device(adev, uc->out_snd_device);
656 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
657 if (new_backend_idx == DSD_NATIVE_BACKEND)
658 audio_route_apply_and_update_path(adev->audio_route,
659 "hph-true-highquality-mode");
660 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
661 (curr_out->bit_width >= 24))
662 audio_route_apply_and_update_path(adev->audio_route,
663 "hph-highquality-mode");
664 enable_asrc_mode(adev);
665 enable_snd_device(adev, uc->out_snd_device);
666 enable_audio_route(adev, uc);
667 break;
668 }
669 }
670 // reset split devices count
671 num_devices = 0;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530672 }
Garmond Leung50058f62017-02-08 09:49:30 -0800673 if (adev->asrc_mode_enabled)
674 break;
675
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530676 }
677 }
678}
679
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700680int pcm_ioctl(struct pcm *pcm, int request, ...)
681{
682 va_list ap;
683 void * arg;
684 int pcm_fd = *(int*)pcm;
685
686 va_start(ap, request);
687 arg = va_arg(ap, void *);
688 va_end(ap);
689
690 return ioctl(pcm_fd, request, arg);
691}
692
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700693int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700694 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800695{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700697 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800698
699 if (usecase == NULL)
700 return -EINVAL;
701
702 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
703
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800704 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800709#ifdef DS1_DOLBY_DAP_ENABLED
710 audio_extn_dolby_set_dmid(adev);
711 audio_extn_dolby_set_endpoint(adev);
712#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700713 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700714 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530715 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700716 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530717 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800718 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700719 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700720 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700721 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 ALOGV("%s: exit", __func__);
723 return 0;
724}
725
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700726int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700730 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800731
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530732 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800733 return -EINVAL;
734
735 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 if (usecase->type == PCM_CAPTURE)
737 snd_device = usecase->in_snd_device;
738 else
739 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800740 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700741 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700742 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700744 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530745 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 ALOGV("%s: exit", __func__);
747 return 0;
748}
749
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700750int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700751 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530753 int i, num_devices = 0;
754 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700755 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
756
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 if (snd_device < SND_DEVICE_MIN ||
758 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800759 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800760 return -EINVAL;
761 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762
763 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700764
765 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
766 ALOGE("%s: Invalid sound device returned", __func__);
767 return -EINVAL;
768 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700769 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700770 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700771 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700772 return 0;
773 }
774
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530775
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700776 if (audio_extn_spkr_prot_is_enabled())
777 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700778
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800779 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
780 audio_extn_spkr_prot_is_enabled()) {
781 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700782 adev->snd_dev_ref_cnt[snd_device]--;
783 return -EINVAL;
784 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200785 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800786 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800787 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200788 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800789 return -EINVAL;
790 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700791 } else if (platform_split_snd_device(adev->platform,
792 snd_device,
793 &num_devices,
794 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530795 for (i = 0; i < num_devices; i++) {
796 enable_snd_device(adev, new_snd_devices[i]);
797 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800798 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700799 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530800
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530801 if (platform_check_codec_asrc_support(adev->platform))
802 check_and_set_asrc_mode(adev, snd_device);
803
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530804 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
805 (audio_extn_a2dp_start_playback() < 0)) {
806 ALOGE(" fail to configure A2dp control path ");
807 return -EINVAL;
808 }
809
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700810 /* due to the possibility of calibration overwrite between listen
811 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700812 audio_extn_sound_trigger_update_device_status(snd_device,
813 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530814 audio_extn_listen_update_device_status(snd_device,
815 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700816 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700817 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700818 audio_extn_sound_trigger_update_device_status(snd_device,
819 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530820 audio_extn_listen_update_device_status(snd_device,
821 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700822 return -EINVAL;
823 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300824 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700825 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530826
827 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
828 !adev->native_playback_enabled &&
829 audio_is_true_native_stream_active(adev)) {
830 ALOGD("%s: %d: napb: enabling native mode in hardware",
831 __func__, __LINE__);
832 audio_route_apply_and_update_path(adev->audio_route,
833 "true-native-mode");
834 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 return 0;
838}
839
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700840int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700841 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530843 int i, num_devices = 0;
844 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700845 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
846
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800847 if (snd_device < SND_DEVICE_MIN ||
848 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800849 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 return -EINVAL;
851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
853 ALOGE("%s: device ref cnt is already 0", __func__);
854 return -EINVAL;
855 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700858
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
860 ALOGE("%s: Invalid sound device returned", __func__);
861 return -EINVAL;
862 }
863
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700865 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530866
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800867 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
868 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700869 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700870 } else if (platform_split_snd_device(adev->platform,
871 snd_device,
872 &num_devices,
873 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530874 for (i = 0; i < num_devices; i++) {
875 disable_snd_device(adev, new_snd_devices[i]);
876 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300877 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700878 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300879 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700880
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530881 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
882 audio_extn_a2dp_stop_playback();
883
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700884 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530885 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530886 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
887 adev->native_playback_enabled) {
888 ALOGD("%s: %d: napb: disabling native mode in hardware",
889 __func__, __LINE__);
890 audio_route_reset_and_update_path(adev->audio_route,
891 "true-native-mode");
892 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530893 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
894 adev->asrc_mode_enabled) {
895 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530896 disable_asrc_mode(adev);
897 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530898 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530899
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200900 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700901 audio_extn_sound_trigger_update_device_status(snd_device,
902 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530903 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800904 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800907 return 0;
908}
909
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700910/*
911 legend:
912 uc - existing usecase
913 new_uc - new usecase
914 d1, d11, d2 - SND_DEVICE enums
915 a1, a2 - corresponding ANDROID device enums
916 B1, B2 - backend strings
917
918case 1
919 uc->dev d1 (a1) B1
920 new_uc->dev d1 (a1), d2 (a2) B1, B2
921
922 resolution: disable and enable uc->dev on d1
923
924case 2
925 uc->dev d1 (a1) B1
926 new_uc->dev d11 (a1) B1
927
928 resolution: need to switch uc since d1 and d11 are related
929 (e.g. speaker and voice-speaker)
930 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
931
932case 3
933 uc->dev d1 (a1) B1
934 new_uc->dev d2 (a2) B2
935
936 resolution: no need to switch uc
937
938case 4
939 uc->dev d1 (a1) B1
940 new_uc->dev d2 (a2) B1
941
942 resolution: disable enable uc-dev on d2 since backends match
943 we cannot enable two streams on two different devices if they
944 share the same backend. e.g. if offload is on speaker device using
945 QUAD_MI2S backend and a low-latency stream is started on voice-handset
946 using the same backend, offload must also be switched to voice-handset.
947
948case 5
949 uc->dev d1 (a1) B1
950 new_uc->dev d1 (a1), d2 (a2) B1
951
952 resolution: disable enable uc-dev on d2 since backends match
953 we cannot enable two streams on two different devices if they
954 share the same backend.
955
956case 6
957 uc->dev d1 (a1) B1
958 new_uc->dev d2 (a1) B2
959
960 resolution: no need to switch
961
962case 7
963 uc->dev d1 (a1), d2 (a2) B1, B2
964 new_uc->dev d1 (a1) B1
965
966 resolution: no need to switch
967
968*/
969static snd_device_t derive_playback_snd_device(void * platform,
970 struct audio_usecase *uc,
971 struct audio_usecase *new_uc,
972 snd_device_t new_snd_device)
973{
974 audio_devices_t a1 = uc->stream.out->devices;
975 audio_devices_t a2 = new_uc->stream.out->devices;
976
977 snd_device_t d1 = uc->out_snd_device;
978 snd_device_t d2 = new_snd_device;
979
980 // Treat as a special case when a1 and a2 are not disjoint
981 if ((a1 != a2) && (a1 & a2)) {
982 snd_device_t d3[2];
983 int num_devices = 0;
984 int ret = platform_split_snd_device(platform,
985 popcount(a1) > 1 ? d1 : d2,
986 &num_devices,
987 d3);
988 if (ret < 0) {
989 if (ret != -ENOSYS) {
990 ALOGW("%s failed to split snd_device %d",
991 __func__,
992 popcount(a1) > 1 ? d1 : d2);
993 }
994 goto end;
995 }
996
997 // NB: case 7 is hypothetical and isn't a practical usecase yet.
998 // But if it does happen, we need to give priority to d2 if
999 // the combo devices active on the existing usecase share a backend.
1000 // This is because we cannot have a usecase active on a combo device
1001 // and a new usecase requests one device in this combo pair.
1002 if (platform_check_backends_match(d3[0], d3[1])) {
1003 return d2; // case 5
1004 } else {
1005 return d1; // case 1
1006 }
1007 } else {
1008 if (platform_check_backends_match(d1, d2)) {
1009 return d2; // case 2, 4
1010 } else {
1011 return d1; // case 6, 3
1012 }
1013 }
1014
1015end:
1016 return d2; // return whatever was calculated before.
1017}
1018
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301020 struct audio_usecase *uc_info,
1021 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022{
1023 struct listnode *node;
1024 struct audio_usecase *usecase;
1025 bool switch_device[AUDIO_USECASE_MAX];
1026 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001027 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301028 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 /*
1030 * This function is to make sure that all the usecases that are active on
1031 * the hardware codec backend are always routed to any one device that is
1032 * handled by the hardware codec.
1033 * For example, if low-latency and deep-buffer usecases are currently active
1034 * on speaker and out_set_parameters(headset) is received on low-latency
1035 * output, then we have to make sure deep-buffer is also switched to headset,
1036 * because of the limitation that both the devices cannot be enabled
1037 * at the same time as they share the same backend.
1038 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001039 /*
1040 * This call is to check if we need to force routing for a particular stream
1041 * If there is a backend configuration change for the device when a
1042 * new stream starts, then ADM needs to be closed and re-opened with the new
1043 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001044 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001045 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001046 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1047 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301048 /* For a2dp device reconfigure all active sessions
1049 * with new AFE encoder format based on a2dp state
1050 */
1051 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1052 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1053 audio_extn_a2dp_is_force_device_switch()) {
1054 force_routing = true;
1055 force_restart_session = true;
1056 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301057 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001060 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001061 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1063 switch_device[i] = false;
1064
1065 list_for_each(node, &adev->usecase_list) {
1066 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001067
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301068 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1069 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301070 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301071 platform_get_snd_device_name(usecase->out_snd_device),
1072 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001073 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301074 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001075 (derive_playback_snd_device(adev->platform,
1076 usecase, uc_info,
1077 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301078 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1079 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301080 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301081 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1082 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1083 ((force_restart_session) ||
1084 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301085
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301086 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1087 __func__, use_case_table[usecase->id],
1088 platform_get_snd_device_name(usecase->out_snd_device));
1089 disable_audio_route(adev, usecase);
1090 switch_device[usecase->id] = true;
1091 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 }
1093 }
1094
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1096 num_uc_to_switch);
1097
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001099 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301101 /* Make sure the previous devices to be disabled first and then enable the
1102 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 list_for_each(node, &adev->usecase_list) {
1104 usecase = node_to_item(node, struct audio_usecase, list);
1105 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001106 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 }
1108 }
1109
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001110 list_for_each(node, &adev->usecase_list) {
1111 usecase = node_to_item(node, struct audio_usecase, list);
1112 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001114 }
1115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 /* Re-route all the usecases on the shared backend other than the
1118 specified usecase to new snd devices */
1119 list_for_each(node, &adev->usecase_list) {
1120 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301121 /* Update the out_snd_device only before enabling the audio route */
1122 if (switch_device[usecase->id]) {
1123 usecase->out_snd_device = snd_device;
1124 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301125 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301126 use_case_table[usecase->id],
1127 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001128 /* Update voc calibration before enabling VoIP route */
1129 if (usecase->type == VOIP_CALL)
1130 status = platform_switch_voice_call_device_post(adev->platform,
1131 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001132 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301133 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 }
1136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 }
1138}
1139
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301140static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001141 struct audio_usecase *uc_info,
1142 snd_device_t snd_device)
1143{
1144 struct listnode *node;
1145 struct audio_usecase *usecase;
1146 bool switch_device[AUDIO_USECASE_MAX];
1147 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301148 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001149 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001150
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301151 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1152 snd_device);
1153 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301154
1155 /*
1156 * Make sure out devices is checked against out codec backend device and
1157 * also in devices against in codec backend. Checking out device against in
1158 * codec backend or vice versa causes issues.
1159 */
1160 if (uc_info->type == PCM_CAPTURE)
1161 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 /*
1163 * This function is to make sure that all the active capture usecases
1164 * are always routed to the same input sound device.
1165 * For example, if audio-record and voice-call usecases are currently
1166 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1167 * is received for voice call then we have to make sure that audio-record
1168 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1169 * because of the limitation that two devices cannot be enabled
1170 * at the same time if they share the same backend.
1171 */
1172 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1173 switch_device[i] = false;
1174
1175 list_for_each(node, &adev->usecase_list) {
1176 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301177 /*
1178 * TODO: Enhance below condition to handle BT sco/USB multi recording
1179 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001180 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301182 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301183 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301184 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001185 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001186 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1188 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001189 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001190 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 switch_device[usecase->id] = true;
1192 num_uc_to_switch++;
1193 }
1194 }
1195
1196 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001197 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001198
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301199 /* Make sure the previous devices to be disabled first and then enable the
1200 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001204 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001205 }
1206 }
1207
1208 list_for_each(node, &adev->usecase_list) {
1209 usecase = node_to_item(node, struct audio_usecase, list);
1210 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001211 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 }
1213 }
1214
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 /* Re-route all the usecases on the shared backend other than the
1216 specified usecase to new snd devices */
1217 list_for_each(node, &adev->usecase_list) {
1218 usecase = node_to_item(node, struct audio_usecase, list);
1219 /* Update the in_snd_device only before enabling the audio route */
1220 if (switch_device[usecase->id] ) {
1221 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001222 if (usecase->type != VOICE_CALL) {
1223 /* Update voc calibration before enabling VoIP route */
1224 if (usecase->type == VOIP_CALL)
1225 status = platform_switch_voice_call_device_post(adev->platform,
1226 usecase->out_snd_device,
1227 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301228 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001229 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 }
1231 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 }
1233}
1234
Mingming Yin3a941d42016-02-17 18:08:05 -08001235static void reset_hdmi_sink_caps(struct stream_out *out) {
1236 int i = 0;
1237
1238 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1239 out->supported_channel_masks[i] = 0;
1240 }
1241 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1242 out->supported_formats[i] = 0;
1243 }
1244 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1245 out->supported_sample_rates[i] = 0;
1246 }
1247}
1248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001250static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251{
Mingming Yin3a941d42016-02-17 18:08:05 -08001252 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001253 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254
Mingming Yin3a941d42016-02-17 18:08:05 -08001255 reset_hdmi_sink_caps(out);
1256
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001257 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001258 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001259 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001260 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001261 }
1262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001265 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001266 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001267 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1268 case 6:
1269 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1270 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1271 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1272 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1273 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1274 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 break;
1276 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001277 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001278 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 break;
1280 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001281
1282 // check channel format caps
1283 i = 0;
1284 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1285 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1286 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1287 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1288 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1289 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1290 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1291 }
1292
1293 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1294 ALOGV(":%s HDMI supports DTS format", __func__);
1295 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1296 }
1297
1298 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1299 ALOGV(":%s HDMI supports DTS HD format", __func__);
1300 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1301 }
1302
1303
1304 // check sample rate caps
1305 i = 0;
1306 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1307 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1308 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1309 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1310 }
1311 }
1312
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001313 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314}
1315
Alexy Josephb1379942016-01-29 15:49:38 -08001316audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001317 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001318{
1319 struct audio_usecase *usecase;
1320 struct listnode *node;
1321
1322 list_for_each(node, &adev->usecase_list) {
1323 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001324 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001325 ALOGV("%s: usecase id %d", __func__, usecase->id);
1326 return usecase->id;
1327 }
1328 }
1329 return USECASE_INVALID;
1330}
1331
Alexy Josephb1379942016-01-29 15:49:38 -08001332struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001333 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334{
1335 struct audio_usecase *usecase;
1336 struct listnode *node;
1337
1338 list_for_each(node, &adev->usecase_list) {
1339 usecase = node_to_item(node, struct audio_usecase, list);
1340 if (usecase->id == uc_id)
1341 return usecase;
1342 }
1343 return NULL;
1344}
1345
Dhananjay Kumard4833242016-10-06 22:09:12 +05301346struct stream_in *get_next_active_input(const struct audio_device *adev)
1347{
1348 struct audio_usecase *usecase;
1349 struct listnode *node;
1350
1351 list_for_each_reverse(node, &adev->usecase_list) {
1352 usecase = node_to_item(node, struct audio_usecase, list);
1353 if (usecase->type == PCM_CAPTURE)
1354 return usecase->stream.in;
1355 }
1356 return NULL;
1357}
1358
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301359/*
1360 * is a true native playback active
1361 */
1362bool audio_is_true_native_stream_active(struct audio_device *adev)
1363{
1364 bool active = false;
1365 int i = 0;
1366 struct listnode *node;
1367
1368 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1369 ALOGV("%s:napb: not in true mode or non hdphones device",
1370 __func__);
1371 active = false;
1372 goto exit;
1373 }
1374
1375 list_for_each(node, &adev->usecase_list) {
1376 struct audio_usecase *uc;
1377 uc = node_to_item(node, struct audio_usecase, list);
1378 struct stream_out *curr_out =
1379 (struct stream_out*) uc->stream.out;
1380
1381 if (curr_out && PCM_PLAYBACK == uc->type) {
1382 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1383 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1384 uc->id, curr_out->sample_rate,
1385 curr_out->bit_width,
1386 platform_get_snd_device_name(uc->out_snd_device));
1387
1388 if (is_offload_usecase(uc->id) &&
1389 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1390 active = true;
1391 ALOGD("%s:napb:native stream detected", __func__);
1392 }
1393 }
1394 }
1395exit:
1396 return active;
1397}
1398
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301399/*
1400 * if native DSD playback active
1401 */
1402bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1403{
1404 bool active = false;
1405 struct listnode *node = NULL;
1406 struct audio_usecase *uc = NULL;
1407 struct stream_out *curr_out = NULL;
1408
1409 list_for_each(node, &adev->usecase_list) {
1410 uc = node_to_item(node, struct audio_usecase, list);
1411 curr_out = (struct stream_out*) uc->stream.out;
1412
1413 if (curr_out && PCM_PLAYBACK == uc->type &&
1414 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1415 active = true;
1416 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301417 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301418 }
1419 }
1420 return active;
1421}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301422
1423static bool force_device_switch(struct audio_usecase *usecase)
1424{
1425 bool ret = false;
1426 bool is_it_true_mode = false;
1427
1428 if (is_offload_usecase(usecase->id) &&
1429 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001430 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1431 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1432 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301433 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1434 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1435 (!is_it_true_mode && adev->native_playback_enabled)){
1436 ret = true;
1437 ALOGD("napb: time to toggle native mode");
1438 }
1439 }
1440
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301441 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301442 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1443 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301444 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001445 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301446 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301447 ALOGD("Force a2dp device switch to update new encoder config");
1448 ret = true;
1449 }
1450
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301451 return ret;
1452}
1453
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001454int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 snd_device_t out_snd_device = SND_DEVICE_NONE;
1457 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 struct audio_usecase *usecase = NULL;
1459 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001460 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001461 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001462 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301465 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 usecase = get_usecase_from_list(adev, uc_id);
1468 if (usecase == NULL) {
1469 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1470 return -EINVAL;
1471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001473 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001474 (usecase->type == VOIP_CALL) ||
1475 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301476 if(usecase->stream.out == NULL) {
1477 ALOGE("%s: stream.out is NULL", __func__);
1478 return -EINVAL;
1479 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001480 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001481 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001482 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 usecase->devices = usecase->stream.out->devices;
1484 } else {
1485 /*
1486 * If the voice call is active, use the sound devices of voice call usecase
1487 * so that it would not result any device switch. All the usecases will
1488 * be switched to new device when select_devices() is called for voice call
1489 * usecase. This is to avoid switching devices for voice call when
1490 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001491 * choose voice call device only if the use case device is
1492 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001494 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001495 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001496 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001497 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1498 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301499 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1500 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001501 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 in_snd_device = vc_usecase->in_snd_device;
1503 out_snd_device = vc_usecase->out_snd_device;
1504 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001505 } else if (voice_extn_compress_voip_is_active(adev)) {
1506 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001507 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001508 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1509 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001510 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001511 in_snd_device = voip_usecase->in_snd_device;
1512 out_snd_device = voip_usecase->out_snd_device;
1513 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001514 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001515 hfp_ucid = audio_extn_hfp_get_usecase();
1516 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001517 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001518 in_snd_device = hfp_usecase->in_snd_device;
1519 out_snd_device = hfp_usecase->out_snd_device;
1520 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 }
1522 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301523 if (usecase->stream.out == NULL) {
1524 ALOGE("%s: stream.out is NULL", __func__);
1525 return -EINVAL;
1526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 usecase->devices = usecase->stream.out->devices;
1528 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001529 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001530 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001531 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001532 if (usecase->stream.out == adev->primary_output &&
1533 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001534 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001535 select_devices(adev, adev->active_input->usecase);
1536 }
1537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301539 if (usecase->stream.in == NULL) {
1540 ALOGE("%s: stream.in is NULL", __func__);
1541 return -EINVAL;
1542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 usecase->devices = usecase->stream.in->device;
1544 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001545 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001546 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001547 if (adev->active_input &&
1548 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301549 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1550 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1551 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001552 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001553 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001554 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1555 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001556 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001557 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001558 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 }
1560 }
1561
1562 if (out_snd_device == usecase->out_snd_device &&
1563 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301564
1565 if (!force_device_switch(usecase))
1566 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 }
1568
sangwoobc677242013-08-08 16:53:43 +09001569 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001570 out_snd_device, platform_get_snd_device_name(out_snd_device),
1571 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 /*
1574 * Limitation: While in call, to do a device switch we need to disable
1575 * and enable both RX and TX devices though one of them is same as current
1576 * device.
1577 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001578 if ((usecase->type == VOICE_CALL) &&
1579 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1580 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001581 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001582 }
1583
1584 if (((usecase->type == VOICE_CALL) ||
1585 (usecase->type == VOIP_CALL)) &&
1586 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1587 /* Disable sidetone only if voice/voip call already exists */
1588 if (voice_is_call_state_active(adev) ||
1589 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001590 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001591
1592 /* Disable aanc only if voice call exists */
1593 if (voice_is_call_state_active(adev))
1594 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001595 }
1596
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001597 /* Disable current sound devices */
1598 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001599 disable_audio_route(adev, usecase);
1600 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 }
1602
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 disable_audio_route(adev, usecase);
1605 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 }
1607
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001608 /* Applicable only on the targets that has external modem.
1609 * New device information should be sent to modem before enabling
1610 * the devices to reduce in-call device switch time.
1611 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001612 if ((usecase->type == VOICE_CALL) &&
1613 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1614 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001615 status = platform_switch_voice_call_enable_device_config(adev->platform,
1616 out_snd_device,
1617 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001618 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001619
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 /* Enable new sound devices */
1621 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001622 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001623 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
1625
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001626 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301627 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001628 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001629 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630
Avinash Vaish71a8b972014-07-24 15:36:33 +05301631 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001632 status = platform_switch_voice_call_device_post(adev->platform,
1633 out_snd_device,
1634 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301635 enable_audio_route_for_voice_usecases(adev, usecase);
1636 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001637
sangwoo170731f2013-06-08 15:36:36 +09001638 usecase->in_snd_device = in_snd_device;
1639 usecase->out_snd_device = out_snd_device;
1640
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301641 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1642 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301643 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001644 if ((24 == usecase->stream.out->bit_width) &&
1645 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1646 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1647 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1648 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1649 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1650 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1651 /*
1652 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1653 * configured device sample rate, if not update the COPP rate to be equal to the
1654 * device sample rate, else open COPP at stream sample rate
1655 */
1656 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1657 usecase->stream.out->sample_rate,
1658 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301659 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1660 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001661 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1662 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1663 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1664 }
1665
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001666 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001667 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001668 audio_extn_gef_notify_device_config(
1669 usecase->stream.out->devices,
1670 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001671 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001672 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001673 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301674 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001675 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001676
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001677 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001678 /* Enable aanc only if voice call exists */
1679 if (voice_is_call_state_active(adev))
1680 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1681
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001682 /* Enable sidetone only if other voice/voip call already exists */
1683 if (voice_is_call_state_active(adev) ||
1684 voice_extn_compress_voip_is_started(adev))
1685 voice_set_sidetone(adev, out_snd_device, true);
1686 }
1687
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001688 /* Applicable only on the targets that has external modem.
1689 * Enable device command should be sent to modem only after
1690 * enabling voice call mixer controls
1691 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001692 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001693 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1694 out_snd_device,
1695 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301696 ALOGD("%s: done",__func__);
1697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 return status;
1699}
1700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701static int stop_input_stream(struct stream_in *in)
1702{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301703 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 struct audio_usecase *uc_info;
1705 struct audio_device *adev = in->dev;
1706
Eric Laurent994a6932013-07-17 11:51:42 -07001707 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709 uc_info = get_usecase_from_list(adev, in->usecase);
1710 if (uc_info == NULL) {
1711 ALOGE("%s: Could not find the usecase (%d) in the list",
1712 __func__, in->usecase);
1713 return -EINVAL;
1714 }
1715
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001716 /* Close in-call recording streams */
1717 voice_check_and_stop_incall_rec_usecase(adev, in);
1718
Eric Laurent150dbfe2013-02-27 14:31:02 -08001719 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001720 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001721
1722 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001723 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001725 list_remove(&uc_info->list);
1726 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001728 adev->active_input = get_next_active_input(adev);
1729
Eric Laurent994a6932013-07-17 11:51:42 -07001730 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 return ret;
1732}
1733
1734int start_input_stream(struct stream_in *in)
1735{
1736 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001737 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 struct audio_usecase *uc_info;
1739 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301740 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Mingming Yin2664a5b2015-09-03 10:53:11 -07001742 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1743 if (get_usecase_from_list(adev, usecase) == NULL)
1744 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301745 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1746 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001747
Naresh Tanniru80659832014-06-04 18:17:56 +05301748
1749 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301750 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301751 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301752 goto error_config;
1753 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301754
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001755 /* Check if source matches incall recording usecase criteria */
1756 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1757 if (ret)
1758 goto error_config;
1759 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001760 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1761
1762 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1763 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1764 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001765 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001766 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001767
Eric Laurentb23d5282013-05-14 15:27:20 -07001768 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769 if (in->pcm_device_id < 0) {
1770 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1771 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001772 ret = -EINVAL;
1773 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775
1776 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001778
1779 if (!uc_info) {
1780 ret = -ENOMEM;
1781 goto error_config;
1782 }
1783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 uc_info->id = in->usecase;
1785 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001786 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001787 uc_info->devices = in->device;
1788 uc_info->in_snd_device = SND_DEVICE_NONE;
1789 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001791 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301792 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1793 adev->perf_lock_opts,
1794 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301797 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1798 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001799
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301800 if (audio_extn_cin_attached_usecase(in->usecase)) {
1801 ret = audio_extn_cin_start_input_stream(in);
1802 if (ret)
1803 goto error_open;
1804 else
1805 goto done_open;
1806 }
1807
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001808 unsigned int flags = PCM_IN;
1809 unsigned int pcm_open_retry_count = 0;
1810
1811 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1812 flags |= PCM_MMAP | PCM_NOIRQ;
1813 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001814 } else if (in->realtime) {
1815 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001816 }
1817
1818 while (1) {
1819 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1820 flags, &in->config);
1821 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1822 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1823 if (in->pcm != NULL) {
1824 pcm_close(in->pcm);
1825 in->pcm = NULL;
1826 }
1827 if (pcm_open_retry_count-- == 0) {
1828 ret = -EIO;
1829 goto error_open;
1830 }
1831 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1832 continue;
1833 }
1834 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001836
1837 ALOGV("%s: pcm_prepare", __func__);
1838 ret = pcm_prepare(in->pcm);
1839 if (ret < 0) {
1840 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1841 pcm_close(in->pcm);
1842 in->pcm = NULL;
1843 goto error_open;
1844 }
1845
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001846 register_in_stream(in);
1847 if (in->realtime) {
1848 ret = pcm_start(in->pcm);
1849 if (ret < 0)
1850 goto error_open;
1851 }
1852
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301853done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301854 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001855 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001856
Eric Laurentc8400632013-02-14 19:04:54 -08001857 return ret;
1858
1859error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301860 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001862error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301863 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301864 /*
1865 * sleep 50ms to allow sufficient time for kernel
1866 * drivers to recover incases like SSR.
1867 */
1868 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001870
1871 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872}
1873
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001874void lock_input_stream(struct stream_in *in)
1875{
1876 pthread_mutex_lock(&in->pre_lock);
1877 pthread_mutex_lock(&in->lock);
1878 pthread_mutex_unlock(&in->pre_lock);
1879}
1880
1881void lock_output_stream(struct stream_out *out)
1882{
1883 pthread_mutex_lock(&out->pre_lock);
1884 pthread_mutex_lock(&out->lock);
1885 pthread_mutex_unlock(&out->pre_lock);
1886}
1887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888/* must be called with out->lock locked */
1889static int send_offload_cmd_l(struct stream_out* out, int command)
1890{
1891 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1892
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001893 if (!cmd) {
1894 ALOGE("failed to allocate mem for command 0x%x", command);
1895 return -ENOMEM;
1896 }
1897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 ALOGVV("%s %d", __func__, command);
1899
1900 cmd->cmd = command;
1901 list_add_tail(&out->offload_cmd_list, &cmd->node);
1902 pthread_cond_signal(&out->offload_cond);
1903 return 0;
1904}
1905
1906/* must be called iwth out->lock locked */
1907static void stop_compressed_output_l(struct stream_out *out)
1908{
1909 out->offload_state = OFFLOAD_STATE_IDLE;
1910 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001911 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001912 if (out->compr != NULL) {
1913 compress_stop(out->compr);
1914 while (out->offload_thread_blocked) {
1915 pthread_cond_wait(&out->cond, &out->lock);
1916 }
1917 }
1918}
1919
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001920bool is_offload_usecase(audio_usecase_t uc_id)
1921{
1922 unsigned int i;
1923 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1924 if (uc_id == offload_usecases[i])
1925 return true;
1926 }
1927 return false;
1928}
1929
vivek mehta446c3962015-09-14 10:57:35 -07001930static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001931{
vivek mehta446c3962015-09-14 10:57:35 -07001932 audio_usecase_t ret_uc = USECASE_INVALID;
1933 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001934 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001935 if (!adev->multi_offload_enable) {
1936 if (is_direct_pcm)
1937 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1938 else
1939 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001940
vivek mehta446c3962015-09-14 10:57:35 -07001941 pthread_mutex_lock(&adev->lock);
1942 if (get_usecase_from_list(adev, ret_uc) != NULL)
1943 ret_uc = USECASE_INVALID;
1944 pthread_mutex_unlock(&adev->lock);
1945
1946 return ret_uc;
1947 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001948
1949 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001950 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1951 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1952 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1953 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001954 break;
1955 }
1956 }
vivek mehta446c3962015-09-14 10:57:35 -07001957
1958 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1959 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001960}
1961
1962static void free_offload_usecase(struct audio_device *adev,
1963 audio_usecase_t uc_id)
1964{
vivek mehta446c3962015-09-14 10:57:35 -07001965 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001966 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001967
1968 if (!adev->multi_offload_enable)
1969 return;
1970
1971 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1972 if (offload_usecases[offload_uc_index] == uc_id) {
1973 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001974 break;
1975 }
1976 }
1977 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1978}
1979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980static void *offload_thread_loop(void *context)
1981{
1982 struct stream_out *out = (struct stream_out *) context;
1983 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001984 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001986 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1987 set_sched_policy(0, SP_FOREGROUND);
1988 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1989
1990 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001991 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 for (;;) {
1993 struct offload_cmd *cmd = NULL;
1994 stream_callback_event_t event;
1995 bool send_callback = false;
1996
1997 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1998 __func__, list_empty(&out->offload_cmd_list),
1999 out->offload_state);
2000 if (list_empty(&out->offload_cmd_list)) {
2001 ALOGV("%s SLEEPING", __func__);
2002 pthread_cond_wait(&out->offload_cond, &out->lock);
2003 ALOGV("%s RUNNING", __func__);
2004 continue;
2005 }
2006
2007 item = list_head(&out->offload_cmd_list);
2008 cmd = node_to_item(item, struct offload_cmd, node);
2009 list_remove(item);
2010
2011 ALOGVV("%s STATE %d CMD %d out->compr %p",
2012 __func__, out->offload_state, cmd->cmd, out->compr);
2013
2014 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2015 free(cmd);
2016 break;
2017 }
2018
2019 if (out->compr == NULL) {
2020 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002021 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 pthread_cond_signal(&out->cond);
2023 continue;
2024 }
2025 out->offload_thread_blocked = true;
2026 pthread_mutex_unlock(&out->lock);
2027 send_callback = false;
2028 switch(cmd->cmd) {
2029 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002030 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002032 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 send_callback = true;
2034 event = STREAM_CBK_EVENT_WRITE_READY;
2035 break;
2036 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002037 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302038 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002039 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302040 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002041 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302042 if (ret < 0)
2043 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302044 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302045 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002046 compress_drain(out->compr);
2047 else
2048 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302049 if (ret != -ENETRESET) {
2050 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302051 pthread_mutex_lock(&out->lock);
2052 out->send_new_metadata = 1;
2053 out->send_next_track_params = true;
2054 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302055 event = STREAM_CBK_EVENT_DRAIN_READY;
2056 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2057 } else
2058 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059 break;
2060 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002061 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002063 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 send_callback = true;
2065 event = STREAM_CBK_EVENT_DRAIN_READY;
2066 break;
2067 default:
2068 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2069 break;
2070 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002071 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002072 out->offload_thread_blocked = false;
2073 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002074 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002075 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002077 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 free(cmd);
2079 }
2080
2081 pthread_cond_signal(&out->cond);
2082 while (!list_empty(&out->offload_cmd_list)) {
2083 item = list_head(&out->offload_cmd_list);
2084 list_remove(item);
2085 free(node_to_item(item, struct offload_cmd, node));
2086 }
2087 pthread_mutex_unlock(&out->lock);
2088
2089 return NULL;
2090}
2091
2092static int create_offload_callback_thread(struct stream_out *out)
2093{
2094 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2095 list_init(&out->offload_cmd_list);
2096 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2097 offload_thread_loop, out);
2098 return 0;
2099}
2100
2101static int destroy_offload_callback_thread(struct stream_out *out)
2102{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002103 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104 stop_compressed_output_l(out);
2105 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2106
2107 pthread_mutex_unlock(&out->lock);
2108 pthread_join(out->offload_thread, (void **) NULL);
2109 pthread_cond_destroy(&out->offload_cond);
2110
2111 return 0;
2112}
2113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114static int stop_output_stream(struct stream_out *out)
2115{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302116 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 struct audio_usecase *uc_info;
2118 struct audio_device *adev = out->dev;
2119
Eric Laurent994a6932013-07-17 11:51:42 -07002120 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002121 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 uc_info = get_usecase_from_list(adev, out->usecase);
2123 if (uc_info == NULL) {
2124 ALOGE("%s: Could not find the usecase (%d) in the list",
2125 __func__, out->usecase);
2126 return -EINVAL;
2127 }
2128
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302130 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002131 if (adev->visualizer_stop_output != NULL)
2132 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002133
2134 audio_extn_dts_remove_state_notifier_node(out->usecase);
2135
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002136 if (adev->offload_effects_stop_output != NULL)
2137 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2138 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002139
Eric Laurent150dbfe2013-02-27 14:31:02 -08002140 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002141 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002142
2143 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002144 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002146 list_remove(&uc_info->list);
2147 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002149 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302150 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002151 ALOGV("Disable passthrough , reset mixer to pcm");
2152 /* NO_PASSTHROUGH */
2153 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002154 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002155 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2156 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002157
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302158 /* Must be called after removing the usecase from list */
2159 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302160 audio_extn_keep_alive_start();
2161
Eric Laurent994a6932013-07-17 11:51:42 -07002162 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 return ret;
2164}
2165
2166int start_output_stream(struct stream_out *out)
2167{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 struct audio_usecase *uc_info;
2170 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302171 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002172 char mixer_ctl_name[128];
2173 struct mixer_ctl *ctl = NULL;
2174 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002176 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2177 ret = -EINVAL;
2178 goto error_config;
2179 }
2180
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302181 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2182 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2183 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302184
Naresh Tanniru80659832014-06-04 18:17:56 +05302185 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302186 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302187 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302188 goto error_config;
2189 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302190
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302191 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2192 if (!audio_extn_a2dp_is_ready()) {
2193 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2194 //combo usecase just by pass a2dp
2195 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2196 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2197 } else {
2198 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2199 ret = -EAGAIN;
2200 goto error_config;
2201 }
2202 }
2203 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002204 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 if (out->pcm_device_id < 0) {
2206 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2207 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002208 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002209 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 }
2211
2212 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002213
2214 if (!uc_info) {
2215 ret = -ENOMEM;
2216 goto error_config;
2217 }
2218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 uc_info->id = out->usecase;
2220 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002221 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002222 uc_info->devices = out->devices;
2223 uc_info->in_snd_device = SND_DEVICE_NONE;
2224 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002225 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302227 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2228 adev->perf_lock_opts,
2229 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302230
2231 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2232 audio_extn_keep_alive_stop();
2233 if (audio_extn_passthru_is_enabled() &&
2234 audio_extn_passthru_is_passthrough_stream(out)) {
2235 audio_extn_passthru_on_start(out);
2236 audio_extn_passthru_update_stream_configuration(adev, out);
2237 }
2238 }
2239
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002240 select_devices(adev, out->usecase);
2241
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002242 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2243 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002244 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002245 unsigned int flags = PCM_OUT;
2246 unsigned int pcm_open_retry_count = 0;
2247 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2248 flags |= PCM_MMAP | PCM_NOIRQ;
2249 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002250 } else if (out->realtime) {
2251 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002252 } else
2253 flags |= PCM_MONOTONIC;
2254
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002255 if ((adev->vr_audio_mode_enabled) &&
2256 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2257 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2258 "PCM_Dev %d Topology", out->pcm_device_id);
2259 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2260 if (!ctl) {
2261 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2262 __func__, mixer_ctl_name);
2263 } else {
2264 //if success use ULLPP
2265 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2266 __func__, mixer_ctl_name, out->pcm_device_id);
2267 //There is a still a possibility that some sessions
2268 // that request for FAST|RAW when 3D audio is active
2269 //can go through ULLPP. Ideally we expects apps to
2270 //listen to audio focus and stop concurrent playback
2271 //Also, we will look for mode flag (voice_in_communication)
2272 //before enabling the realtime flag.
2273 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2274 }
2275 }
2276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002277 while (1) {
2278 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2279 flags, &out->config);
2280 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2281 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2282 if (out->pcm != NULL) {
2283 pcm_close(out->pcm);
2284 out->pcm = NULL;
2285 }
2286 if (pcm_open_retry_count-- == 0) {
2287 ret = -EIO;
2288 goto error_open;
2289 }
2290 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2291 continue;
2292 }
2293 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002294 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002295
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002296 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2297 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002298
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002299 ALOGV("%s: pcm_prepare", __func__);
2300 if (pcm_is_ready(out->pcm)) {
2301 ret = pcm_prepare(out->pcm);
2302 if (ret < 0) {
2303 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2304 pcm_close(out->pcm);
2305 out->pcm = NULL;
2306 goto error_open;
2307 }
2308 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002310 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2311 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002313 out->compr = compress_open(adev->snd_card,
2314 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 COMPRESS_IN, &out->compr_config);
2316 if (out->compr && !is_compress_ready(out->compr)) {
2317 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2318 compress_close(out->compr);
2319 out->compr = NULL;
2320 ret = -EIO;
2321 goto error_open;
2322 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302323 /* compress_open sends params of the track, so reset the flag here */
2324 out->is_compr_metadata_avail = false;
2325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002326 if (out->offload_callback)
2327 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002328
Fred Oh3f43e742015-03-04 18:42:34 -08002329 /* Since small bufs uses blocking writes, a write will be blocked
2330 for the default max poll time (20s) in the event of an SSR.
2331 Reduce the poll time to observe and deal with SSR faster.
2332 */
Ashish Jain5106d362016-05-11 19:23:33 +05302333 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002334 compress_set_max_poll_wait(out->compr, 1000);
2335 }
2336
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002337 audio_extn_dts_create_state_notifier_node(out->usecase);
2338 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2339 popcount(out->channel_mask),
2340 out->playback_started);
2341
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002342#ifdef DS1_DOLBY_DDP_ENABLED
2343 if (audio_extn_is_dolby_format(out->format))
2344 audio_extn_dolby_send_ddp_endp_params(adev);
2345#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302346 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2347 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002348 if (adev->visualizer_start_output != NULL)
2349 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2350 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302351 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002352 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002353 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002355
2356 if (ret == 0) {
2357 register_out_stream(out);
2358 if (out->realtime) {
2359 ret = pcm_start(out->pcm);
2360 if (ret < 0)
2361 goto error_open;
2362 }
2363 }
2364
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302365 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002366 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002367
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002368 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302370 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002372error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302373 /*
2374 * sleep 50ms to allow sufficient time for kernel
2375 * drivers to recover incases like SSR.
2376 */
2377 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379}
2380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381static int check_input_parameters(uint32_t sample_rate,
2382 audio_format_t format,
2383 int channel_count)
2384{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002385 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302387 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2388 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2389 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002390 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302391 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002392
2393 switch (channel_count) {
2394 case 1:
2395 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302396 case 3:
2397 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002398 case 6:
2399 break;
2400 default:
2401 ret = -EINVAL;
2402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403
2404 switch (sample_rate) {
2405 case 8000:
2406 case 11025:
2407 case 12000:
2408 case 16000:
2409 case 22050:
2410 case 24000:
2411 case 32000:
2412 case 44100:
2413 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302414 case 96000:
2415 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 break;
2417 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002418 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419 }
2420
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002421 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422}
2423
2424static size_t get_input_buffer_size(uint32_t sample_rate,
2425 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002426 int channel_count,
2427 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428{
2429 size_t size = 0;
2430
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002431 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2432 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002434 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002435 if (is_low_latency)
2436 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302437
2438 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002440 /* make sure the size is multiple of 32 bytes
2441 * At 48 kHz mono 16-bit PCM:
2442 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2443 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2444 */
2445 size += 0x1f;
2446 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002447
2448 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449}
2450
Ashish Jain058165c2016-09-28 23:18:48 +05302451static size_t get_output_period_size(uint32_t sample_rate,
2452 audio_format_t format,
2453 int channel_count,
2454 int duration /*in millisecs*/)
2455{
2456 size_t size = 0;
2457 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2458
2459 if ((duration == 0) || (sample_rate == 0) ||
2460 (bytes_per_sample == 0) || (channel_count == 0)) {
2461 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2462 bytes_per_sample, channel_count);
2463 return -EINVAL;
2464 }
2465
2466 size = (sample_rate *
2467 duration *
2468 bytes_per_sample *
2469 channel_count) / 1000;
2470 /*
2471 * To have same PCM samples for all channels, the buffer size requires to
2472 * be multiple of (number of channels * bytes per sample)
2473 * For writes to succeed, the buffer must be written at address which is multiple of 32
2474 */
2475 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2476
2477 return (size/(channel_count * bytes_per_sample));
2478}
2479
Ashish Jain5106d362016-05-11 19:23:33 +05302480static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2481{
2482 uint64_t actual_frames_rendered = 0;
2483 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2484
2485 /* This adjustment accounts for buffering after app processor.
2486 * It is based on estimated DSP latency per use case, rather than exact.
2487 */
2488 int64_t platform_latency = platform_render_latency(out->usecase) *
2489 out->sample_rate / 1000000LL;
2490
2491 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2492 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2493 * hence only estimate.
2494 */
2495 int64_t signed_frames = out->written - kernel_buffer_size;
2496
2497 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2498
2499 if (signed_frames > 0)
2500 actual_frames_rendered = signed_frames;
2501
2502 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2503 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2504 (long long int)out->written, (int)kernel_buffer_size,
2505 audio_bytes_per_sample(out->compr_config.codec->format),
2506 popcount(out->channel_mask));
2507
2508 return actual_frames_rendered;
2509}
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2512{
2513 struct stream_out *out = (struct stream_out *)stream;
2514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516}
2517
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002518static int out_set_sample_rate(struct audio_stream *stream __unused,
2519 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520{
2521 return -ENOSYS;
2522}
2523
2524static size_t out_get_buffer_size(const struct audio_stream *stream)
2525{
2526 struct stream_out *out = (struct stream_out *)stream;
2527
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002528 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002529 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002530 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2531 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302532 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302533 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002535 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002536 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537}
2538
2539static uint32_t out_get_channels(const struct audio_stream *stream)
2540{
2541 struct stream_out *out = (struct stream_out *)stream;
2542
2543 return out->channel_mask;
2544}
2545
2546static audio_format_t out_get_format(const struct audio_stream *stream)
2547{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002548 struct stream_out *out = (struct stream_out *)stream;
2549
2550 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551}
2552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002553static int out_set_format(struct audio_stream *stream __unused,
2554 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555{
2556 return -ENOSYS;
2557}
2558
2559static int out_standby(struct audio_stream *stream)
2560{
2561 struct stream_out *out = (struct stream_out *)stream;
2562 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302564 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2565 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002567 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002569 if (adev->adm_deregister_stream)
2570 adev->adm_deregister_stream(adev->adm_data, out->handle);
2571
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002572 if (is_offload_usecase(out->usecase))
2573 stop_compressed_output_l(out);
2574
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002575 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002577 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2578 voice_extn_compress_voip_close_output_stream(stream);
2579 pthread_mutex_unlock(&adev->lock);
2580 pthread_mutex_unlock(&out->lock);
2581 ALOGD("VOIP output entered standby");
2582 return 0;
2583 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 if (out->pcm) {
2585 pcm_close(out->pcm);
2586 out->pcm = NULL;
2587 }
2588 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002589 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302590 out->send_next_track_params = false;
2591 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002592 out->gapless_mdata.encoder_delay = 0;
2593 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 if (out->compr != NULL) {
2595 compress_close(out->compr);
2596 out->compr = NULL;
2597 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002598 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002600 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 }
2602 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302603 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 return 0;
2605}
2606
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002607static int out_dump(const struct audio_stream *stream __unused,
2608 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609{
2610 return 0;
2611}
2612
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002613static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2614{
2615 int ret = 0;
2616 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002617
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002618 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002619 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002620 return -EINVAL;
2621 }
2622
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302623 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002624
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002625 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2626 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302627 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002628 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002629 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2630 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302631 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002632 }
2633
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002634 ALOGV("%s new encoder delay %u and padding %u", __func__,
2635 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2636
2637 return 0;
2638}
2639
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002640static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2641{
2642 return out == adev->primary_output || out == adev->voice_tx_output;
2643}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2646{
2647 struct stream_out *out = (struct stream_out *)stream;
2648 struct audio_device *adev = out->dev;
2649 struct str_parms *parms;
2650 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002651 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652
sangwoobc677242013-08-08 16:53:43 +09002653 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002654 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302656 if (!parms)
2657 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002658 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2659 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002661 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002662 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002664 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002665 * When HDMI cable is unplugged the music playback is paused and
2666 * the policy manager sends routing=0. But the audioflinger continues
2667 * to write data until standby time (3sec). As the HDMI core is
2668 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002669 * Avoid this by routing audio to speaker until standby.
2670 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002671 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2672 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302673 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002674 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2675 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302677 /*
2678 * When A2DP is disconnected the
2679 * music playback is paused and the policy manager sends routing=0
2680 * But the audioflingercontinues to write data until standby time
2681 * (3sec). As BT is turned off, the write gets blocked.
2682 * Avoid this by routing audio to speaker until standby.
2683 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002684 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302685 (val == AUDIO_DEVICE_NONE)) {
2686 val = AUDIO_DEVICE_OUT_SPEAKER;
2687 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302688 /* To avoid a2dp to sco overlapping / BT device improper state
2689 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302690 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302691 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2692 if (!audio_extn_a2dp_is_ready()) {
2693 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2694 //combo usecase just by pass a2dp
2695 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2696 val = AUDIO_DEVICE_OUT_SPEAKER;
2697 } else {
2698 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2699 /* update device to a2dp and don't route as BT returned error
2700 * However it is still possible a2dp routing called because
2701 * of current active device disconnection (like wired headset)
2702 */
2703 out->devices = val;
2704 pthread_mutex_unlock(&out->lock);
2705 pthread_mutex_unlock(&adev->lock);
2706 goto error;
2707 }
2708 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302709 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002710 /*
2711 * select_devices() call below switches all the usecases on the same
2712 * backend to the new device. Refer to check_usecases_codec_backend() in
2713 * the select_devices(). But how do we undo this?
2714 *
2715 * For example, music playback is active on headset (deep-buffer usecase)
2716 * and if we go to ringtones and select a ringtone, low-latency usecase
2717 * will be started on headset+speaker. As we can't enable headset+speaker
2718 * and headset devices at the same time, select_devices() switches the music
2719 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2720 * So when the ringtone playback is completed, how do we undo the same?
2721 *
2722 * We are relying on the out_set_parameters() call on deep-buffer output,
2723 * once the ringtone playback is ended.
2724 * NOTE: We should not check if the current devices are same as new devices.
2725 * Because select_devices() must be called to switch back the music
2726 * playback to headset.
2727 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002728 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002729 audio_devices_t new_dev = val;
2730 bool same_dev = out->devices == new_dev;
2731 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002732
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002733 if (output_drives_call(adev, out)) {
2734 if(!voice_is_in_call(adev)) {
2735 if (adev->mode == AUDIO_MODE_IN_CALL) {
2736 adev->current_call_output = out;
2737 ret = voice_start_call(adev);
2738 }
2739 } else {
2740 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002741 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002742 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002743 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002744
2745 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002746 if (!same_dev) {
2747 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302748 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2749 adev->perf_lock_opts,
2750 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002751 if (adev->adm_on_routing_change)
2752 adev->adm_on_routing_change(adev->adm_data,
2753 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002754 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002755 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302756 if (!same_dev)
2757 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002758 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002759 }
2760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002762 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002764
2765 if (out == adev->primary_output) {
2766 pthread_mutex_lock(&adev->lock);
2767 audio_extn_set_parameters(adev, parms);
2768 pthread_mutex_unlock(&adev->lock);
2769 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002770 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002771 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002772 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002773
2774 audio_extn_dts_create_state_notifier_node(out->usecase);
2775 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2776 popcount(out->channel_mask),
2777 out->playback_started);
2778
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002779 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002780 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002781
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302782 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2783 if (err >= 0) {
2784 strlcpy(out->profile, value, sizeof(out->profile));
2785 ALOGV("updating stream profile with value '%s'", out->profile);
2786 lock_output_stream(out);
2787 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2788 &adev->streams_output_cfg_list,
2789 out->devices, out->flags, out->format,
2790 out->sample_rate, out->bit_width,
2791 out->channel_mask, out->profile,
2792 &out->app_type_cfg);
2793 pthread_mutex_unlock(&out->lock);
2794 }
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302797error:
Eric Laurent994a6932013-07-17 11:51:42 -07002798 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 return ret;
2800}
2801
2802static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2803{
2804 struct stream_out *out = (struct stream_out *)stream;
2805 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002806 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 char value[256];
2808 struct str_parms *reply = str_parms_create();
2809 size_t i, j;
2810 int ret;
2811 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002812
2813 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002814 if (reply) {
2815 str_parms_destroy(reply);
2816 }
2817 if (query) {
2818 str_parms_destroy(query);
2819 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002820 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2821 return NULL;
2822 }
2823
Eric Laurent994a6932013-07-17 11:51:42 -07002824 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2826 if (ret >= 0) {
2827 value[0] = '\0';
2828 i = 0;
2829 while (out->supported_channel_masks[i] != 0) {
2830 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2831 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2832 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002833 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002835 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 first = false;
2837 break;
2838 }
2839 }
2840 i++;
2841 }
2842 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2843 str = str_parms_to_str(reply);
2844 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002845 voice_extn_out_get_parameters(out, query, reply);
2846 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002847 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002848 free(str);
2849 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002852
Alexy Joseph62142aa2015-11-16 15:10:34 -08002853
2854 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2855 if (ret >= 0) {
2856 value[0] = '\0';
2857 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2858 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302859 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002860 } else {
2861 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302862 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002863 }
2864 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002865 if (str)
2866 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002867 str = str_parms_to_str(reply);
2868 }
2869
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002870 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2871 if (ret >= 0) {
2872 value[0] = '\0';
2873 i = 0;
2874 first = true;
2875 while (out->supported_formats[i] != 0) {
2876 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2877 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2878 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002879 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002880 }
2881 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2882 first = false;
2883 break;
2884 }
2885 }
2886 i++;
2887 }
2888 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002889 if (str)
2890 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002891 str = str_parms_to_str(reply);
2892 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002893
2894 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2895 if (ret >= 0) {
2896 value[0] = '\0';
2897 i = 0;
2898 first = true;
2899 while (out->supported_sample_rates[i] != 0) {
2900 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2901 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2902 if (!first) {
2903 strlcat(value, "|", sizeof(value));
2904 }
2905 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2906 first = false;
2907 break;
2908 }
2909 }
2910 i++;
2911 }
2912 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2913 if (str)
2914 free(str);
2915 str = str_parms_to_str(reply);
2916 }
2917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 str_parms_destroy(query);
2919 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002920 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 return str;
2922}
2923
2924static uint32_t out_get_latency(const struct audio_stream_out *stream)
2925{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002926 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002928 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929
Alexy Josephaa54c872014-12-03 02:46:47 -08002930 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002931 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002932 } else if (out->realtime) {
2933 // since the buffer won't be filled up faster than realtime,
2934 // return a smaller number
2935 if (out->config.rate)
2936 period_ms = (out->af_period_multiplier * out->config.period_size *
2937 1000) / (out->config.rate);
2938 else
2939 period_ms = 0;
2940 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002941 } else {
2942 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002944 }
2945
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002946 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2947 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2948 latency += audio_extn_a2dp_get_encoder_latency();
2949
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302950 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002951 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952}
2953
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302954static float AmpToDb(float amplification)
2955{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302956 float db = DSD_VOLUME_MIN_DB;
2957 if (amplification > 0) {
2958 db = 20 * log10(amplification);
2959 if(db < DSD_VOLUME_MIN_DB)
2960 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302961 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302962 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302963}
2964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965static int out_set_volume(struct audio_stream_out *stream, float left,
2966 float right)
2967{
Eric Laurenta9024de2013-04-04 09:19:12 -07002968 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 int volume[2];
2970
Eric Laurenta9024de2013-04-04 09:19:12 -07002971 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2972 /* only take left channel into account: the API is for stereo anyway */
2973 out->muted = (left == 0.0f);
2974 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002975 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302976 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002977 /*
2978 * Set mute or umute on HDMI passthrough stream.
2979 * Only take left channel into account.
2980 * Mute is 0 and unmute 1
2981 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302982 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302983 } else if (out->format == AUDIO_FORMAT_DSD){
2984 char mixer_ctl_name[128] = "DSD Volume";
2985 struct audio_device *adev = out->dev;
2986 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2987
2988 if (!ctl) {
2989 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2990 __func__, mixer_ctl_name);
2991 return -EINVAL;
2992 }
2993 volume[0] = (int)(AmpToDb(left));
2994 volume[1] = (int)(AmpToDb(right));
2995 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2996 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002997 } else {
2998 char mixer_ctl_name[128];
2999 struct audio_device *adev = out->dev;
3000 struct mixer_ctl *ctl;
3001 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003002 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003004 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3005 "Compress Playback %d Volume", pcm_device_id);
3006 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3007 if (!ctl) {
3008 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3009 __func__, mixer_ctl_name);
3010 return -EINVAL;
3011 }
3012 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3013 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3014 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3015 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003016 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003017 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 return -ENOSYS;
3020}
3021
3022static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3023 size_t bytes)
3024{
3025 struct stream_out *out = (struct stream_out *)stream;
3026 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303027 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003028 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003030 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303031
Naresh Tanniru80659832014-06-04 18:17:56 +05303032 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003033
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05303034 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303035 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303036 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3037 pthread_mutex_unlock(&out->lock);
3038 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303039 } else {
3040 /* increase written size during SSR to avoid mismatch
3041 * with the written frames count in AF
3042 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003043 // bytes per frame
3044 size_t bpf = audio_bytes_per_sample(out->format) *
3045 audio_channel_count_from_out_mask(out->channel_mask);
3046 if (bpf != 0)
3047 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303048 ALOGD(" %s: sound card is not active/SSR state", __func__);
3049 ret= -EIO;
3050 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303051 }
3052 }
3053
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303054 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303055 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3056 if (audio_bytes_per_sample(out->format) != 0)
3057 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3058 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303059 goto exit;
3060 }
3061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003063 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003064 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003065 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3066 ret = voice_extn_compress_voip_start_output_stream(out);
3067 else
3068 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003069 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003072 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 goto exit;
3074 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003075
3076 if (last_known_cal_step != -1) {
3077 ALOGD("%s: retry previous failed cal level set", __func__);
3078 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3079 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081
Ashish Jain81eb2a82015-05-13 10:52:34 +05303082 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003083 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303084 adev->is_channel_status_set = true;
3085 }
3086
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003087 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003088 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003089 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003090 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003091 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3092 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303093 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3094 ALOGD("copl(%p):send next track params in gapless", out);
3095 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3096 out->send_next_track_params = false;
3097 out->is_compr_metadata_avail = false;
3098 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003099 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303100 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303101 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003102
Ashish Jain83a6cc22016-06-28 14:34:17 +05303103 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303104 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303105 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303106 pthread_mutex_unlock(&out->lock);
3107 return -EINVAL;
3108 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303109 audio_format_t dst_format = out->hal_op_format;
3110 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303111
3112 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3113 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3114
Ashish Jain83a6cc22016-06-28 14:34:17 +05303115 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303116 dst_format,
3117 buffer,
3118 src_format,
3119 frames);
3120
Ashish Jain83a6cc22016-06-28 14:34:17 +05303121 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303122 bytes_to_write);
3123
3124 /*Convert written bytes in audio flinger format*/
3125 if (ret > 0)
3126 ret = ((ret * format_to_bitwidth_table[out->format]) /
3127 format_to_bitwidth_table[dst_format]);
3128 }
3129 } else
3130 ret = compress_write(out->compr, buffer, bytes);
3131
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303132 if (ret < 0)
3133 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303134 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303135 /*msg to cb thread only if non blocking write is enabled*/
3136 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303137 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003138 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303139 } else if (-ENETRESET == ret) {
3140 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3141 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3142 pthread_mutex_unlock(&out->lock);
3143 out_standby(&out->stream.common);
3144 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 }
Ashish Jain5106d362016-05-11 19:23:33 +05303146 if ( ret == (ssize_t)bytes && !out->non_blocking)
3147 out->written += bytes;
3148
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303149 /* Call compr start only when non-zero bytes of data is there to be rendered */
3150 if (!out->playback_started && ret > 0) {
3151 int status = compress_start(out->compr);
3152 if (status < 0) {
3153 ret = status;
3154 ALOGE("%s: compr start failed with err %d", __func__, errno);
3155 goto exit;
3156 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003157 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158 out->playback_started = 1;
3159 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003160
3161 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3162 popcount(out->channel_mask),
3163 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003164 }
3165 pthread_mutex_unlock(&out->lock);
3166 return ret;
3167 } else {
3168 if (out->pcm) {
3169 if (out->muted)
3170 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003171
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303172 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003173
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003174 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003175
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003176 if (out->config.rate)
3177 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3178 out->config.rate;
3179
3180 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3181
3182 request_out_focus(out, ns);
3183
3184 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003185 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003186 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303187 out->convert_buffer != NULL) {
3188
3189 memcpy_by_audio_format(out->convert_buffer,
3190 out->hal_op_format,
3191 buffer,
3192 out->hal_ip_format,
3193 out->config.period_size * out->config.channels);
3194
3195 ret = pcm_write(out->pcm, out->convert_buffer,
3196 (out->config.period_size *
3197 out->config.channels *
3198 format_to_bitwidth_table[out->hal_op_format]));
3199 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003200 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303201 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003202
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003203 release_out_focus(out);
3204
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303205 if (ret < 0)
3206 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303207 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3208 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3209 else
3210 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 }
3213
3214exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303215 /* ToDo: There may be a corner case when SSR happens back to back during
3216 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303217 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303218 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303219 }
3220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 pthread_mutex_unlock(&out->lock);
3222
3223 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003224 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003225 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303226 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303227 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303228 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303229 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303230 out->standby = true;
3231 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303233 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3234 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3235 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 }
3237 return bytes;
3238}
3239
3240static int out_get_render_position(const struct audio_stream_out *stream,
3241 uint32_t *dsp_frames)
3242{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003243 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303244 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003245
3246 if (dsp_frames == NULL)
3247 return -EINVAL;
3248
3249 *dsp_frames = 0;
3250 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003251 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303252
3253 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3254 * this operation and adev_close_output_stream(where out gets reset).
3255 */
3256 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3257 *dsp_frames = get_actual_pcm_frames_rendered(out);
3258 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3259 return 0;
3260 }
3261
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003262 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303263 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303264 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003265 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303266 if (ret < 0)
3267 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303269 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 }
3271 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303272 if (-ENETRESET == ret) {
3273 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3274 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3275 return -EINVAL;
3276 } else if(ret < 0) {
3277 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3278 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303279 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3280 /*
3281 * Handle corner case where compress session is closed during SSR
3282 * and timestamp is queried
3283 */
3284 ALOGE(" ERROR: sound card not active, return error");
3285 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303286 } else {
3287 return 0;
3288 }
Zhou Song32a556e2015-05-05 10:46:56 +08003289 } else if (audio_is_linear_pcm(out->format)) {
3290 *dsp_frames = out->written;
3291 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 } else
3293 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294}
3295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003296static int out_add_audio_effect(const struct audio_stream *stream __unused,
3297 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298{
3299 return 0;
3300}
3301
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003302static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3303 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304{
3305 return 0;
3306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3309 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return -EINVAL;
3312}
3313
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003314static int out_get_presentation_position(const struct audio_stream_out *stream,
3315 uint64_t *frames, struct timespec *timestamp)
3316{
3317 struct stream_out *out = (struct stream_out *)stream;
3318 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003319 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003320
Ashish Jain5106d362016-05-11 19:23:33 +05303321 /* below piece of code is not guarded against any lock because audioFliner serializes
3322 * this operation and adev_close_output_stream( where out gets reset).
3323 */
3324 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3325 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3326 *frames = get_actual_pcm_frames_rendered(out);
3327 /* this is the best we can do */
3328 clock_gettime(CLOCK_MONOTONIC, timestamp);
3329 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3330 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3331 return 0;
3332 }
3333
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003334 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003335
Ashish Jain5106d362016-05-11 19:23:33 +05303336 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3337 ret = compress_get_tstamp(out->compr, &dsp_frames,
3338 &out->sample_rate);
3339 ALOGVV("%s rendered frames %ld sample_rate %d",
3340 __func__, dsp_frames, out->sample_rate);
3341 *frames = dsp_frames;
3342 if (ret < 0)
3343 ret = -errno;
3344 if (-ENETRESET == ret) {
3345 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3346 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3347 ret = -EINVAL;
3348 } else
3349 ret = 0;
3350 /* this is the best we can do */
3351 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003352 } else {
3353 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003354 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003355 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3356 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003357 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003358 // This adjustment accounts for buffering after app processor.
3359 // It is based on estimated DSP latency per use case, rather than exact.
3360 signed_frames -=
3361 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3362
Eric Laurent949a0892013-09-20 09:20:13 -07003363 // It would be unusual for this value to be negative, but check just in case ...
3364 if (signed_frames >= 0) {
3365 *frames = signed_frames;
3366 ret = 0;
3367 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003368 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303369 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3370 *frames = out->written;
3371 clock_gettime(CLOCK_MONOTONIC, timestamp);
3372 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003373 }
3374 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003375 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003376 return ret;
3377}
3378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379static int out_set_callback(struct audio_stream_out *stream,
3380 stream_callback_t callback, void *cookie)
3381{
3382 struct stream_out *out = (struct stream_out *)stream;
3383
3384 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003385 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 out->offload_callback = callback;
3387 out->offload_cookie = cookie;
3388 pthread_mutex_unlock(&out->lock);
3389 return 0;
3390}
3391
3392static int out_pause(struct audio_stream_out* stream)
3393{
3394 struct stream_out *out = (struct stream_out *)stream;
3395 int status = -ENOSYS;
3396 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003397 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003398 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003399 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003400 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303401 struct audio_device *adev = out->dev;
3402 int snd_scard_state = get_snd_card_state(adev);
3403
3404 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3405 status = compress_pause(out->compr);
3406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003407 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003408
Mingming Yin21854652016-04-13 11:54:02 -07003409 if (audio_extn_passthru_is_active()) {
3410 ALOGV("offload use case, pause passthru");
3411 audio_extn_passthru_on_pause(out);
3412 }
3413
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303414 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003415 audio_extn_dts_notify_playback_state(out->usecase, 0,
3416 out->sample_rate, popcount(out->channel_mask),
3417 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003418 }
3419 pthread_mutex_unlock(&out->lock);
3420 }
3421 return status;
3422}
3423
3424static int out_resume(struct audio_stream_out* stream)
3425{
3426 struct stream_out *out = (struct stream_out *)stream;
3427 int status = -ENOSYS;
3428 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003429 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003430 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003432 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303434 struct audio_device *adev = out->dev;
3435 int snd_scard_state = get_snd_card_state(adev);
3436
Mingming Yin21854652016-04-13 11:54:02 -07003437 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3438 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3439 pthread_mutex_lock(&out->dev->lock);
3440 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003441 pthread_mutex_unlock(&out->dev->lock);
3442 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303443 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003444 }
3445 if (!status) {
3446 out->offload_state = OFFLOAD_STATE_PLAYING;
3447 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303448 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003449 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3450 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003451 }
3452 pthread_mutex_unlock(&out->lock);
3453 }
3454 return status;
3455}
3456
3457static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3458{
3459 struct stream_out *out = (struct stream_out *)stream;
3460 int status = -ENOSYS;
3461 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003462 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003463 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3465 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3466 else
3467 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3468 pthread_mutex_unlock(&out->lock);
3469 }
3470 return status;
3471}
3472
3473static int out_flush(struct audio_stream_out* stream)
3474{
3475 struct stream_out *out = (struct stream_out *)stream;
3476 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003477 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003478 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003479 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003480 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3481 stop_compressed_output_l(out);
3482 out->written = 0;
3483 } else {
3484 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3485 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003487 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 return 0;
3489 }
3490 return -ENOSYS;
3491}
3492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493/** audio_stream_in implementation **/
3494static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3495{
3496 struct stream_in *in = (struct stream_in *)stream;
3497
3498 return in->config.rate;
3499}
3500
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003501static int in_set_sample_rate(struct audio_stream *stream __unused,
3502 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503{
3504 return -ENOSYS;
3505}
3506
3507static size_t in_get_buffer_size(const struct audio_stream *stream)
3508{
3509 struct stream_in *in = (struct stream_in *)stream;
3510
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003511 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3512 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003513 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3514 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303515 else if(audio_extn_cin_attached_usecase(in->usecase))
3516 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003517
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003518 return in->config.period_size * in->af_period_multiplier *
3519 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520}
3521
3522static uint32_t in_get_channels(const struct audio_stream *stream)
3523{
3524 struct stream_in *in = (struct stream_in *)stream;
3525
3526 return in->channel_mask;
3527}
3528
3529static audio_format_t in_get_format(const struct audio_stream *stream)
3530{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003531 struct stream_in *in = (struct stream_in *)stream;
3532
3533 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534}
3535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003536static int in_set_format(struct audio_stream *stream __unused,
3537 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
3539 return -ENOSYS;
3540}
3541
3542static int in_standby(struct audio_stream *stream)
3543{
3544 struct stream_in *in = (struct stream_in *)stream;
3545 struct audio_device *adev = in->dev;
3546 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303547 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3548 stream, in->usecase, use_case_table[in->usecase]);
3549
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003550 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003551 if (!in->standby && in->is_st_session) {
3552 ALOGD("%s: sound trigger pcm stop lab", __func__);
3553 audio_extn_sound_trigger_stop_lab(in);
3554 in->standby = 1;
3555 }
3556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003558 if (adev->adm_deregister_stream)
3559 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3560
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003561 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003563 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3564 voice_extn_compress_voip_close_input_stream(stream);
3565 ALOGD("VOIP input entered standby");
3566 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303567 if (audio_extn_cin_attached_usecase(in->usecase))
3568 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003569 if (in->pcm) {
3570 pcm_close(in->pcm);
3571 in->pcm = NULL;
3572 }
3573 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003574 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003575 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 }
3577 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003578 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 return status;
3580}
3581
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003582static int in_dump(const struct audio_stream *stream __unused,
3583 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584{
3585 return 0;
3586}
3587
3588static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3589{
3590 struct stream_in *in = (struct stream_in *)stream;
3591 struct audio_device *adev = in->dev;
3592 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003594 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303596 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 parms = str_parms_create_str(kvpairs);
3598
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303599 if (!parms)
3600 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003601 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003602 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003603
3604 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3605 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 val = atoi(value);
3607 /* no audio source uses val == 0 */
3608 if ((in->source != val) && (val != 0)) {
3609 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003610 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3611 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3612 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003613 (in->config.rate == 8000 || in->config.rate == 16000 ||
3614 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003615 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003616 err = voice_extn_compress_voip_open_input_stream(in);
3617 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003618 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003619 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003620 }
3621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 }
3623 }
3624
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003625 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3626 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003628 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 in->device = val;
3630 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003631 if (!in->standby && !in->is_st_session) {
3632 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003633 if (adev->adm_on_routing_change)
3634 adev->adm_on_routing_change(adev->adm_data,
3635 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003636 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638 }
3639 }
3640
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303641 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3642 if (err >= 0) {
3643 strlcpy(in->profile, value, sizeof(in->profile));
3644 ALOGV("updating stream profile with value '%s'", in->profile);
3645 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3646 &adev->streams_input_cfg_list,
3647 in->device, in->flags, in->format,
3648 in->sample_rate, in->bit_width,
3649 in->profile, &in->app_type_cfg);
3650 }
3651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003653 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654
3655 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303656error:
Eric Laurent994a6932013-07-17 11:51:42 -07003657 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 return ret;
3659}
3660
3661static char* in_get_parameters(const struct audio_stream *stream,
3662 const char *keys)
3663{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003664 struct stream_in *in = (struct stream_in *)stream;
3665 struct str_parms *query = str_parms_create_str(keys);
3666 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003667 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003668
3669 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003670 if (reply) {
3671 str_parms_destroy(reply);
3672 }
3673 if (query) {
3674 str_parms_destroy(query);
3675 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003676 ALOGE("in_get_parameters: failed to create query or reply");
3677 return NULL;
3678 }
3679
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003680 ALOGV("%s: enter: keys - %s", __func__, keys);
3681
3682 voice_extn_in_get_parameters(in, query, reply);
3683
3684 str = str_parms_to_str(reply);
3685 str_parms_destroy(query);
3686 str_parms_destroy(reply);
3687
3688 ALOGV("%s: exit: returns - %s", __func__, str);
3689 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690}
3691
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003692static int in_set_gain(struct audio_stream_in *stream __unused,
3693 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694{
3695 return 0;
3696}
3697
3698static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3699 size_t bytes)
3700{
3701 struct stream_in *in = (struct stream_in *)stream;
3702 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303703 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303704 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303705 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003707 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303708
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003709 if (in->is_st_session) {
3710 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3711 /* Read from sound trigger HAL */
3712 audio_extn_sound_trigger_read(in, buffer, bytes);
3713 pthread_mutex_unlock(&in->lock);
3714 return bytes;
3715 }
3716
Ashish Jainbbce4322016-02-16 13:25:27 +05303717 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003718 ALOGD(" %s: sound card is not active/SSR state", __func__);
3719 ret= -EIO;;
3720 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303721 }
3722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003724 pthread_mutex_lock(&adev->lock);
3725 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3726 ret = voice_extn_compress_voip_start_input_stream(in);
3727 else
3728 ret = start_input_stream(in);
3729 pthread_mutex_unlock(&adev->lock);
3730 if (ret != 0) {
3731 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 }
3733 in->standby = 0;
3734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003736 // what's the duration requested by the client?
3737 long ns = 0;
3738
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303739 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003740 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3741 in->config.rate;
3742
3743 request_in_focus(in, ns);
3744 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003745
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303746 if (audio_extn_cin_attached_usecase(in->usecase)) {
3747 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3748 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303749 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003750 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303751 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003752 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003753 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003754 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303755 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003756 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303757 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3758 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3759 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3760 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303761 ret = -EINVAL;
3762 goto exit;
3763 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303764 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303765 ret = -errno;
3766 }
3767 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303768 /* bytes read is always set to bytes for non compress usecases */
3769 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 }
3771
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003772 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 /*
3775 * Instead of writing zeroes here, we could trust the hardware
3776 * to always provide zeroes when muted.
3777 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303778 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3779 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 memset(buffer, 0, bytes);
3781
3782exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303783 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303784 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003785 if (-ENETRESET == ret)
3786 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 pthread_mutex_unlock(&in->lock);
3789
3790 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303791 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303792 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303793 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303794 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303795 in->standby = true;
3796 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303797 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3798 bytes_read = bytes;
3799 memset(buffer, 0, bytes);
3800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003802 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303803 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303804 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303806 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807}
3808
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003809static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810{
3811 return 0;
3812}
3813
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003814static int add_remove_audio_effect(const struct audio_stream *stream,
3815 effect_handle_t effect,
3816 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003818 struct stream_in *in = (struct stream_in *)stream;
3819 int status = 0;
3820 effect_descriptor_t desc;
3821
3822 status = (*effect)->get_descriptor(effect, &desc);
3823 if (status != 0)
3824 return status;
3825
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003826 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003827 pthread_mutex_lock(&in->dev->lock);
3828 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3829 in->enable_aec != enable &&
3830 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3831 in->enable_aec = enable;
3832 if (!in->standby)
3833 select_devices(in->dev, in->usecase);
3834 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003835 if (in->enable_ns != enable &&
3836 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3837 in->enable_ns = enable;
3838 if (!in->standby)
3839 select_devices(in->dev, in->usecase);
3840 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003841 pthread_mutex_unlock(&in->dev->lock);
3842 pthread_mutex_unlock(&in->lock);
3843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 return 0;
3845}
3846
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003847static int in_add_audio_effect(const struct audio_stream *stream,
3848 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849{
Eric Laurent994a6932013-07-17 11:51:42 -07003850 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003851 return add_remove_audio_effect(stream, effect, true);
3852}
3853
3854static int in_remove_audio_effect(const struct audio_stream *stream,
3855 effect_handle_t effect)
3856{
Eric Laurent994a6932013-07-17 11:51:42 -07003857 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003858 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859}
3860
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303861int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 audio_io_handle_t handle,
3863 audio_devices_t devices,
3864 audio_output_flags_t flags,
3865 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003866 struct audio_stream_out **stream_out,
3867 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868{
3869 struct audio_device *adev = (struct audio_device *)dev;
3870 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303871 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003872 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303875
3876 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3877 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003878 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303879 return -EINVAL;
3880 }
3881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3883
Mingming Yin3a941d42016-02-17 18:08:05 -08003884 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3885 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303886 devices, flags, &out->stream);
3887
3888
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003889 if (!out) {
3890 return -ENOMEM;
3891 }
3892
Haynes Mathew George204045b2015-02-25 20:32:03 -08003893 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003894 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003895 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 if (devices == AUDIO_DEVICE_NONE)
3898 devices = AUDIO_DEVICE_OUT_SPEAKER;
3899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 out->flags = flags;
3901 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003902 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003903 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003904 out->sample_rate = config->sample_rate;
3905 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3906 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003907 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003908 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003909 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303910 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911
Mingming Yin3a941d42016-02-17 18:08:05 -08003912 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3913 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3914 pthread_mutex_lock(&adev->lock);
3915 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3916 ret = read_hdmi_sink_caps(out);
3917 pthread_mutex_unlock(&adev->lock);
3918 if (ret != 0) {
3919 if (ret == -ENOSYS) {
3920 /* ignore and go with default */
3921 ret = 0;
3922 } else {
3923 ALOGE("error reading hdmi sink caps");
3924 goto error_open;
3925 }
3926 }
3927 }
3928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003930 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303931 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3932 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003933 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3934 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3935
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003936 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003937 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3938 /*
3939 * Do not handle stereo output in Multi-channel cases
3940 * Stereo case is handled in normal playback path
3941 */
3942 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3943 ret = AUDIO_CHANNEL_OUT_STEREO;
3944 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003945
3946 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3947 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003948 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003949 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003950 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003951
3952 if (config->sample_rate == 0)
3953 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3954 if (config->channel_mask == 0)
3955 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003956 if (config->format == 0)
3957 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003958
3959 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003961 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3963 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003965 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003967 } 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 -08003968 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003969 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003970 ret = voice_extn_compress_voip_open_output_stream(out);
3971 if (ret != 0) {
3972 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3973 __func__, ret);
3974 goto error_open;
3975 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003976 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3977 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3978
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3980 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3981 ALOGE("%s: Unsupported Offload information", __func__);
3982 ret = -EINVAL;
3983 goto error_open;
3984 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003985
Mingming Yin3a941d42016-02-17 18:08:05 -08003986 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003987 if(config->offload_info.format == 0)
3988 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003989 if (config->offload_info.sample_rate == 0)
3990 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003991 }
3992
Mingming Yin90310102013-11-13 16:57:00 -08003993 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303994 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003995 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003996 ret = -EINVAL;
3997 goto error_open;
3998 }
3999
4000 out->compr_config.codec = (struct snd_codec *)
4001 calloc(1, sizeof(struct snd_codec));
4002
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004003 if (!out->compr_config.codec) {
4004 ret = -ENOMEM;
4005 goto error_open;
4006 }
4007
vivek mehta0ea887a2015-08-26 14:01:20 -07004008 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304009 out->stream.pause = out_pause;
4010 out->stream.flush = out_flush;
4011 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07004012 out->usecase = get_offload_usecase(adev, true);
4013 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004014 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07004015 out->stream.set_callback = out_set_callback;
4016 out->stream.pause = out_pause;
4017 out->stream.resume = out_resume;
4018 out->stream.drain = out_drain;
4019 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07004020 out->usecase = get_offload_usecase(adev, false);
4021 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004022 }
vivek mehta446c3962015-09-14 10:57:35 -07004023
4024 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004025 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4026 config->format == 0 && config->sample_rate == 0 &&
4027 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004028 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004029 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4030 } else {
4031 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4032 ret = -EEXIST;
4033 goto error_open;
4034 }
vivek mehta446c3962015-09-14 10:57:35 -07004035 }
4036
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004037 if (config->offload_info.channel_mask)
4038 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004039 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004040 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004041 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004042 } else {
4043 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
4044 ret = -EINVAL;
4045 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004046 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004047
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004048 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004049 out->sample_rate = config->offload_info.sample_rate;
4050
Mingming Yin3ee55c62014-08-04 14:23:35 -07004051 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004052
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304053 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4054 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4055 audio_extn_dolby_send_ddp_endp_params(adev);
4056 audio_extn_dolby_set_dmid(adev);
4057 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004059 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004060 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 out->compr_config.codec->bit_rate =
4062 config->offload_info.bit_rate;
4063 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304064 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304066 /* Update bit width only for non passthrough usecases.
4067 * For passthrough usecases, the output will always be opened @16 bit
4068 */
4069 if (!audio_extn_passthru_is_passthrough_stream(out))
4070 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004071 /*TODO: Do we need to change it for passthrough */
4072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004073
Manish Dewangana6fc5442015-08-24 20:30:31 +05304074 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4075 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304076 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304077 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304078 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4079 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304080
4081 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4082 AUDIO_FORMAT_PCM) {
4083
4084 /*Based on platform support, configure appropriate alsa format for corresponding
4085 *hal input format.
4086 */
4087 out->compr_config.codec->format = hal_format_to_alsa(
4088 config->offload_info.format);
4089
Ashish Jain83a6cc22016-06-28 14:34:17 +05304090 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304091 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304092 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304093
4094 /*for direct PCM playback populate bit_width based on selected alsa format as
4095 *hal input format and alsa format might differ based on platform support.
4096 */
4097 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304098 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304099
4100 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4101
4102 /* Check if alsa session is configured with the same format as HAL input format,
4103 * if not then derive correct fragment size needed to accomodate the
4104 * conversion of HAL input format to alsa format.
4105 */
4106 audio_extn_utils_update_direct_pcm_fragment_size(out);
4107
4108 /*if hal input and output fragment size is different this indicates HAL input format is
4109 *not same as the alsa format
4110 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304111 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304112 /*Allocate a buffer to convert input data to the alsa configured format.
4113 *size of convert buffer is equal to the size required to hold one fragment size
4114 *worth of pcm data, this is because flinger does not write more than fragment_size
4115 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304116 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4117 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304118 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4119 ret = -ENOMEM;
4120 goto error_open;
4121 }
4122 }
4123 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4124 out->compr_config.fragment_size =
4125 audio_extn_passthru_get_buffer_size(&config->offload_info);
4126 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4127 } else {
4128 out->compr_config.fragment_size =
4129 platform_get_compress_offload_buffer_size(&config->offload_info);
4130 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4131 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004132
Amit Shekhar6f461b12014-08-01 14:52:58 -07004133 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304134 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004135
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304136 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4137 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4138 }
4139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004140 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4141 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004142
Alexy Josephaa54c872014-12-03 02:46:47 -08004143
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004144 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304145 out->send_next_track_params = false;
4146 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004147 out->offload_state = OFFLOAD_STATE_IDLE;
4148 out->playback_started = 0;
4149
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004150 audio_extn_dts_create_state_notifier_node(out->usecase);
4151
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004152 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4153 __func__, config->offload_info.version,
4154 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304155
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304156 /* Check if DSD audio format is supported in codec
4157 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304158 */
4159
4160 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304161 (!platform_check_codec_dsd_support(adev->platform) ||
4162 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304163 ret = -EINVAL;
4164 goto error_open;
4165 }
4166
Ashish Jain5106d362016-05-11 19:23:33 +05304167 /* Disable gapless if any of the following is true
4168 * passthrough playback
4169 * AV playback
4170 * Direct PCM playback
4171 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304172 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304173 (config->format == AUDIO_FORMAT_DSD) ||
4174 config->offload_info.has_video ||
4175 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304176 check_and_set_gapless_mode(adev, false);
4177 } else
4178 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004179
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304180 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004181 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4182 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304183 if (config->format == AUDIO_FORMAT_DSD) {
4184 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4185 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4186 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004187
4188 create_offload_callback_thread(out);
4189
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004190 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304191 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004192 if (ret != 0) {
4193 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4194 __func__, ret);
4195 goto error_open;
4196 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004197 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4198 if (config->sample_rate == 0)
4199 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4200 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4201 config->sample_rate != 8000) {
4202 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4203 ret = -EINVAL;
4204 goto error_open;
4205 }
4206 out->sample_rate = config->sample_rate;
4207 out->config.rate = config->sample_rate;
4208 if (config->format == AUDIO_FORMAT_DEFAULT)
4209 config->format = AUDIO_FORMAT_PCM_16_BIT;
4210 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4211 config->format = AUDIO_FORMAT_PCM_16_BIT;
4212 ret = -EINVAL;
4213 goto error_open;
4214 }
4215 out->format = config->format;
4216 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4217 out->config = pcm_config_afe_proxy_playback;
4218 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004219 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304220 unsigned int channels = 0;
4221 /*Update config params to default if not set by the caller*/
4222 if (config->sample_rate == 0)
4223 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4224 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4225 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4226 if (config->format == AUDIO_FORMAT_DEFAULT)
4227 config->format = AUDIO_FORMAT_PCM_16_BIT;
4228
4229 channels = audio_channel_count_from_out_mask(out->channel_mask);
4230
Ashish Jain83a6cc22016-06-28 14:34:17 +05304231 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4232 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004233 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4234 out->flags);
4235 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304236 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4237 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4238 out->config = pcm_config_low_latency;
4239 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4240 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4241 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304242 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4243 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4244 if (out->config.period_size <= 0) {
4245 ALOGE("Invalid configuration period size is not valid");
4246 ret = -EINVAL;
4247 goto error_open;
4248 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304249 } else {
4250 /* primary path is the default path selected if no other outputs are available/suitable */
4251 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4252 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4253 }
4254 out->hal_ip_format = format = out->format;
4255 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4256 out->hal_op_format = pcm_format_to_hal(out->config.format);
4257 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4258 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004259 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304260 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304261 if (out->hal_ip_format != out->hal_op_format) {
4262 uint32_t buffer_size = out->config.period_size *
4263 format_to_bitwidth_table[out->hal_op_format] *
4264 out->config.channels;
4265 out->convert_buffer = calloc(1, buffer_size);
4266 if (out->convert_buffer == NULL){
4267 ALOGE("Allocation failed for convert buffer for size %d",
4268 out->compr_config.fragment_size);
4269 ret = -ENOMEM;
4270 goto error_open;
4271 }
4272 ALOGD("Convert buffer allocated of size %d", buffer_size);
4273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274 }
4275
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004276 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4277 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304278
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004279 /* TODO remove this hardcoding and check why width is zero*/
4280 if (out->bit_width == 0)
4281 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304282 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004283 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304284 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304285 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304286 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004287 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4288 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4289 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004290 if(adev->primary_output == NULL)
4291 adev->primary_output = out;
4292 else {
4293 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004294 ret = -EEXIST;
4295 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004296 }
4297 }
4298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 /* Check if this usecase is already existing */
4300 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004301 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4302 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004305 ret = -EEXIST;
4306 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 pthread_mutex_unlock(&adev->lock);
4310
4311 out->stream.common.get_sample_rate = out_get_sample_rate;
4312 out->stream.common.set_sample_rate = out_set_sample_rate;
4313 out->stream.common.get_buffer_size = out_get_buffer_size;
4314 out->stream.common.get_channels = out_get_channels;
4315 out->stream.common.get_format = out_get_format;
4316 out->stream.common.set_format = out_set_format;
4317 out->stream.common.standby = out_standby;
4318 out->stream.common.dump = out_dump;
4319 out->stream.common.set_parameters = out_set_parameters;
4320 out->stream.common.get_parameters = out_get_parameters;
4321 out->stream.common.add_audio_effect = out_add_audio_effect;
4322 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4323 out->stream.get_latency = out_get_latency;
4324 out->stream.set_volume = out_set_volume;
4325 out->stream.write = out_write;
4326 out->stream.get_render_position = out_get_render_position;
4327 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004328 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004330 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004332 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004333 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334
4335 config->format = out->stream.common.get_format(&out->stream.common);
4336 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4337 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4338
4339 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304340 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004341 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004342
4343 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4344 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4345 popcount(out->channel_mask), out->playback_started);
4346
Eric Laurent994a6932013-07-17 11:51:42 -07004347 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004349
4350error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304351 if (out->convert_buffer)
4352 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004353 free(out);
4354 *stream_out = NULL;
4355 ALOGD("%s: exit: ret %d", __func__, ret);
4356 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357}
4358
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304359void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 struct audio_stream_out *stream)
4361{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004362 struct stream_out *out = (struct stream_out *)stream;
4363 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004364 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004365
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304366 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4367
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004368 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304369 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004370 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304371 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004372 if(ret != 0)
4373 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4374 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004375 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004376 out_standby(&stream->common);
4377
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004378 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004379 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004380 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004381 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004382 if (out->compr_config.codec != NULL)
4383 free(out->compr_config.codec);
4384 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004385
Ashish Jain83a6cc22016-06-28 14:34:17 +05304386 if (out->convert_buffer != NULL) {
4387 free(out->convert_buffer);
4388 out->convert_buffer = NULL;
4389 }
4390
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004391 if (adev->voice_tx_output == out)
4392 adev->voice_tx_output = NULL;
4393
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304394 if (adev->primary_output == out)
4395 adev->primary_output = NULL;
4396
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004397 pthread_cond_destroy(&out->cond);
4398 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004400 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401}
4402
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004403static void close_compress_sessions(struct audio_device *adev)
4404{
Mingming Yin7b762e72015-03-04 13:47:32 -08004405 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304406 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004407 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004408 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304409
4410 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004411 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304412 if (is_offload_usecase(usecase->id)) {
4413 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004414 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4415 out = usecase->stream.out;
4416 pthread_mutex_unlock(&adev->lock);
4417 out_standby(&out->stream.common);
4418 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004419 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004420 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304421 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004422 }
4423 pthread_mutex_unlock(&adev->lock);
4424}
4425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4427{
4428 struct audio_device *adev = (struct audio_device *)dev;
4429 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004431 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004432 int ret;
4433 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004435 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304438 if (!parms)
4439 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004440 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4441 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304442 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304443 if (strstr(snd_card_status, "OFFLINE")) {
4444 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304445 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004446 //close compress sessions on OFFLINE status
4447 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304448 } else if (strstr(snd_card_status, "ONLINE")) {
4449 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304450 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004451 //send dts hpx license if enabled
4452 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304453 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304454 }
4455
4456 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004457 status = voice_set_parameters(adev, parms);
4458 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004459 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004461 status = platform_set_parameters(adev->platform, parms);
4462 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004463 goto done;
4464
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004465 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4466 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004467 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4469 adev->bluetooth_nrec = true;
4470 else
4471 adev->bluetooth_nrec = false;
4472 }
4473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004474 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4475 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4477 adev->screen_off = false;
4478 else
4479 adev->screen_off = true;
4480 }
4481
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004482 ret = str_parms_get_int(parms, "rotation", &val);
4483 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004484 bool reverse_speakers = false;
4485 switch(val) {
4486 // FIXME: note that the code below assumes that the speakers are in the correct placement
4487 // relative to the user when the device is rotated 90deg from its default rotation. This
4488 // assumption is device-specific, not platform-specific like this code.
4489 case 270:
4490 reverse_speakers = true;
4491 break;
4492 case 0:
4493 case 90:
4494 case 180:
4495 break;
4496 default:
4497 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004498 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004499 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004500 if (status == 0) {
4501 if (adev->speaker_lr_swap != reverse_speakers) {
4502 adev->speaker_lr_swap = reverse_speakers;
4503 // only update the selected device if there is active pcm playback
4504 struct audio_usecase *usecase;
4505 struct listnode *node;
4506 list_for_each(node, &adev->usecase_list) {
4507 usecase = node_to_item(node, struct audio_usecase, list);
4508 if (usecase->type == PCM_PLAYBACK) {
4509 select_devices(adev, usecase->id);
4510 break;
4511 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004512 }
4513 }
4514 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004515 }
4516
Mingming Yin514a8bc2014-07-29 15:22:21 -07004517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4518 if (ret >= 0) {
4519 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4520 adev->bt_wb_speech_enabled = true;
4521 else
4522 adev->bt_wb_speech_enabled = false;
4523 }
4524
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004525 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4526 if (ret >= 0) {
4527 val = atoi(value);
4528 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004529 ALOGV("cache new ext disp type and edid");
4530 ret = platform_get_ext_disp_type(adev->platform);
4531 if (ret < 0) {
4532 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004533 status = ret;
4534 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004535 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004536 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004537 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004538 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004539 /*
4540 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4541 * Per AudioPolicyManager, USB device is higher priority than WFD.
4542 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4543 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4544 * starting voice call on USB
4545 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004546 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4547 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004548 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4549 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004550 }
vivek mehta344576a2016-04-12 18:56:03 -07004551 ALOGV("detected USB connect .. disable proxy");
4552 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004553 }
4554 }
4555
4556 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4557 if (ret >= 0) {
4558 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004559 /*
4560 * The HDMI / Displayport disconnect handling has been moved to
4561 * audio extension to ensure that its parameters are not
4562 * invalidated prior to updating sysfs of the disconnect event
4563 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4564 */
4565 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004566 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004567 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4568 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304569 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4570 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004571 }
vivek mehta344576a2016-04-12 18:56:03 -07004572 ALOGV("detected USB disconnect .. enable proxy");
4573 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004574 }
4575 }
4576
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304577 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4578 if (ret >= 0) {
4579 struct audio_usecase *usecase;
4580 struct listnode *node;
4581 list_for_each(node, &adev->usecase_list) {
4582 usecase = node_to_item(node, struct audio_usecase, list);
4583 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004584 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304585 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304586 lock_output_stream(usecase->stream.out);
4587 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304588 //force device switch to re configure encoder
4589 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304590 audio_extn_a2dp_set_handoff_mode(false);
4591 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304592 break;
4593 }
4594 }
4595 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004596
4597 //handle vr audio setparam
4598 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4599 value, sizeof(value));
4600 if (ret >= 0) {
4601 ALOGI("Setting vr mode to be %s", value);
4602 if (!strncmp(value, "true", 4)) {
4603 adev->vr_audio_mode_enabled = true;
4604 ALOGI("Setting vr mode to true");
4605 } else if (!strncmp(value, "false", 5)) {
4606 adev->vr_audio_mode_enabled = false;
4607 ALOGI("Setting vr mode to false");
4608 } else {
4609 ALOGI("wrong vr mode set");
4610 }
4611 }
4612
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304613 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004614done:
4615 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004616 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304617error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004618 ALOGV("%s: exit with code(%d)", __func__, status);
4619 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620}
4621
4622static char* adev_get_parameters(const struct audio_hw_device *dev,
4623 const char *keys)
4624{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004625 struct audio_device *adev = (struct audio_device *)dev;
4626 struct str_parms *reply = str_parms_create();
4627 struct str_parms *query = str_parms_create_str(keys);
4628 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304629 char value[256] = {0};
4630 int ret = 0;
4631
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004632 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004633 if (reply) {
4634 str_parms_destroy(reply);
4635 }
4636 if (query) {
4637 str_parms_destroy(query);
4638 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004639 ALOGE("adev_get_parameters: failed to create query or reply");
4640 return NULL;
4641 }
4642
Naresh Tannirud7205b62014-06-20 02:54:48 +05304643 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4644 sizeof(value));
4645 if (ret >=0) {
4646 int val = 1;
4647 pthread_mutex_lock(&adev->snd_card_status.lock);
4648 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4649 val = 0;
4650 pthread_mutex_unlock(&adev->snd_card_status.lock);
4651 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4652 goto exit;
4653 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004654 //handle vr audio getparam
4655
4656 ret = str_parms_get_str(query,
4657 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4658 value, sizeof(value));
4659
4660 if (ret >= 0) {
4661 bool vr_audio_enabled = false;
4662 pthread_mutex_lock(&adev->lock);
4663 vr_audio_enabled = adev->vr_audio_mode_enabled;
4664 pthread_mutex_unlock(&adev->lock);
4665
4666 ALOGI("getting vr mode to %d", vr_audio_enabled);
4667
4668 if (vr_audio_enabled) {
4669 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4670 "true");
4671 goto exit;
4672 } else {
4673 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4674 "false");
4675 goto exit;
4676 }
4677 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004678
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004679 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004680 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004681 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004682 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304683 pthread_mutex_unlock(&adev->lock);
4684
Naresh Tannirud7205b62014-06-20 02:54:48 +05304685exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004686 str = str_parms_to_str(reply);
4687 str_parms_destroy(query);
4688 str_parms_destroy(reply);
4689
4690 ALOGV("%s: exit: returns - %s", __func__, str);
4691 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692}
4693
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004694static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695{
4696 return 0;
4697}
4698
4699static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4700{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004701 int ret;
4702 struct audio_device *adev = (struct audio_device *)dev;
4703 pthread_mutex_lock(&adev->lock);
4704 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004705 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004706 pthread_mutex_unlock(&adev->lock);
4707 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708}
4709
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004710static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4711 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712{
4713 return -ENOSYS;
4714}
4715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004716static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4717 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718{
4719 return -ENOSYS;
4720}
4721
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004722static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4723 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724{
4725 return -ENOSYS;
4726}
4727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004728static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4729 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730{
4731 return -ENOSYS;
4732}
4733
4734static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4735{
4736 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 pthread_mutex_lock(&adev->lock);
4739 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004740 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004742 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004743 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004744 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004745 adev->current_call_output = NULL;
4746 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747 }
4748 pthread_mutex_unlock(&adev->lock);
4749 return 0;
4750}
4751
4752static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4753{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004754 int ret;
4755
4756 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004757 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004758 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4759 pthread_mutex_unlock(&adev->lock);
4760
4761 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762}
4763
4764static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4765{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004766 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767 return 0;
4768}
4769
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004770static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 const struct audio_config *config)
4772{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004773 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004775 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4776 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004777}
4778
4779static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004780 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 audio_devices_t devices,
4782 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004783 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304784 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004785 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004786 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004787{
4788 struct audio_device *adev = (struct audio_device *)dev;
4789 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004790 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004791 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004792 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304793 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304796 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4797 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304799 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800
4801 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004802
4803 if (!in) {
4804 ALOGE("failed to allocate input stream");
4805 return -ENOMEM;
4806 }
4807
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304808 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304809 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4810 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004811 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004812 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814 in->stream.common.get_sample_rate = in_get_sample_rate;
4815 in->stream.common.set_sample_rate = in_set_sample_rate;
4816 in->stream.common.get_buffer_size = in_get_buffer_size;
4817 in->stream.common.get_channels = in_get_channels;
4818 in->stream.common.get_format = in_get_format;
4819 in->stream.common.set_format = in_set_format;
4820 in->stream.common.standby = in_standby;
4821 in->stream.common.dump = in_dump;
4822 in->stream.common.set_parameters = in_set_parameters;
4823 in->stream.common.get_parameters = in_get_parameters;
4824 in->stream.common.add_audio_effect = in_add_audio_effect;
4825 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4826 in->stream.set_gain = in_set_gain;
4827 in->stream.read = in_read;
4828 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4829
4830 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004831 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004833 in->standby = 1;
4834 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004835 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004836 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304838 in->usecase = USECASE_AUDIO_RECORD;
4839 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4840 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4841 is_low_latency = true;
4842#if LOW_LATENCY_CAPTURE_USE_CASE
4843 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4844#endif
4845 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4846 }
4847
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004848 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004849 if (in->realtime) {
4850 in->config = pcm_config_audio_capture_rt;
4851 in->sample_rate = in->config.rate;
4852 in->af_period_multiplier = af_period_multiplier;
4853 } else {
4854 in->config = pcm_config_audio_capture;
4855 in->config.rate = config->sample_rate;
4856 in->sample_rate = config->sample_rate;
4857 in->af_period_multiplier = 1;
4858 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304859 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304861 /* restrict 24 bit capture for unprocessed source only
4862 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4863 */
4864 if (config->format == AUDIO_FORMAT_DEFAULT) {
4865 config->format = AUDIO_FORMAT_PCM_16_BIT;
4866 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4867 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4868 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4869 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4870 bool ret_error = false;
4871 in->bit_width = 24;
4872 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4873 from HAL is 24_packed and 8_24
4874 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4875 24_packed return error indicating supported format is 24_packed
4876 *> In case of any other source requesting 24 bit or float return error
4877 indicating format supported is 16 bit only.
4878
4879 on error flinger will retry with supported format passed
4880 */
4881 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4882 (source != AUDIO_SOURCE_CAMCORDER)) {
4883 config->format = AUDIO_FORMAT_PCM_16_BIT;
4884 if (config->sample_rate > 48000)
4885 config->sample_rate = 48000;
4886 ret_error = true;
4887 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4888 in->config.format = PCM_FORMAT_S24_3LE;
4889 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4890 in->config.format = PCM_FORMAT_S24_LE;
4891 } else {
4892 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4893 ret_error = true;
4894 }
4895
4896 if (ret_error) {
4897 ret = -EINVAL;
4898 goto err_open;
4899 }
4900 }
4901
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304902 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304903 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4904 (adev->mode != AUDIO_MODE_IN_CALL)) {
4905 ret = -EINVAL;
4906 goto err_open;
4907 }
4908
4909 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4910 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004911 if (config->sample_rate == 0)
4912 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4913 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4914 config->sample_rate != 8000) {
4915 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4916 ret = -EINVAL;
4917 goto err_open;
4918 }
4919 if (config->format == AUDIO_FORMAT_DEFAULT)
4920 config->format = AUDIO_FORMAT_PCM_16_BIT;
4921 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4922 config->format = AUDIO_FORMAT_PCM_16_BIT;
4923 ret = -EINVAL;
4924 goto err_open;
4925 }
4926
4927 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4928 in->config = pcm_config_afe_proxy_record;
4929 in->config.channels = channel_count;
4930 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304931 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304932 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4933 in, config, &channel_mask_updated)) {
4934 if (channel_mask_updated == true) {
4935 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4936 __func__, config->channel_mask);
4937 ret = -EINVAL;
4938 goto err_open;
4939 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304940 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004941 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004942 audio_extn_compr_cap_format_supported(config->format) &&
4943 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004944 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304945 } else if (audio_extn_cin_applicable_stream(in)) {
4946 ret = audio_extn_cin_configure_input_stream(in);
4947 if (ret)
4948 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004949 } else {
4950 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004951 if (!in->realtime) {
4952 in->format = config->format;
4953 frame_size = audio_stream_in_frame_size(&in->stream);
4954 buffer_size = get_input_buffer_size(config->sample_rate,
4955 config->format,
4956 channel_count,
4957 is_low_latency);
4958 in->config.period_size = buffer_size / frame_size;
4959 }
4960
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004961 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004962 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004963 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004964 (in->config.rate == 8000 || in->config.rate == 16000 ||
4965 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004966 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4967 voice_extn_compress_voip_open_input_stream(in);
4968 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304971 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4972 &adev->streams_input_cfg_list,
4973 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304974 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304975
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004976 /* This stream could be for sound trigger lab,
4977 get sound trigger pcm if present */
4978 audio_extn_sound_trigger_check_and_get_session(in);
4979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004981 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004982 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983
4984err_open:
4985 free(in);
4986 *stream_in = NULL;
4987 return ret;
4988}
4989
4990static void adev_close_input_stream(struct audio_hw_device *dev,
4991 struct audio_stream_in *stream)
4992{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004993 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004994 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004995 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304996
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304997 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004998
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304999 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005000 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305001
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005002 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305003 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005004 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305005 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005006 if (ret != 0)
5007 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5008 __func__, ret);
5009 } else
5010 in_standby(&stream->common);
5011
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005012 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005013 audio_extn_ssr_deinit();
5014 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305016 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005017 audio_extn_compr_cap_format_supported(in->config.format))
5018 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305019
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305020 if (audio_extn_cin_attached_usecase(in->usecase))
5021 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005022
Mingming Yinfd7607b2016-01-22 12:48:44 -08005023 if (in->is_st_session) {
5024 ALOGV("%s: sound trigger pcm stop lab", __func__);
5025 audio_extn_sound_trigger_stop_lab(in);
5026 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005027 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028 return;
5029}
5030
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005031static int adev_dump(const audio_hw_device_t *device __unused,
5032 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033{
5034 return 0;
5035}
5036
5037static int adev_close(hw_device_t *device)
5038{
5039 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005040
5041 if (!adev)
5042 return 0;
5043
5044 pthread_mutex_lock(&adev_init_lock);
5045
5046 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005047 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005048 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305049 audio_extn_utils_release_streams_cfg_lists(
5050 &adev->streams_output_cfg_list,
5051 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305052 if (audio_extn_qaf_is_enabled())
5053 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005054 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005055 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005056 free(adev->snd_dev_ref_cnt);
5057 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005058 if (adev->adm_deinit)
5059 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305060 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005061 free(device);
5062 adev = NULL;
5063 }
5064 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005066 return 0;
5067}
5068
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005069/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5070 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5071 * just that it _might_ work.
5072 */
5073static int period_size_is_plausible_for_low_latency(int period_size)
5074{
5075 switch (period_size) {
5076 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005077 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005078 case 240:
5079 case 320:
5080 case 480:
5081 return 1;
5082 default:
5083 return 0;
5084 }
5085}
5086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087static int adev_open(const hw_module_t *module, const char *name,
5088 hw_device_t **device)
5089{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305090 int ret;
5091
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005092 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005093 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5094
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005095 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005096 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005097 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005098 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005099 ALOGD("%s: returning existing instance of adev", __func__);
5100 ALOGD("%s: exit", __func__);
5101 pthread_mutex_unlock(&adev_init_lock);
5102 return 0;
5103 }
5104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005105 adev = calloc(1, sizeof(struct audio_device));
5106
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005107 if (!adev) {
5108 pthread_mutex_unlock(&adev_init_lock);
5109 return -ENOMEM;
5110 }
5111
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005112 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5115 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5116 adev->device.common.module = (struct hw_module_t *)module;
5117 adev->device.common.close = adev_close;
5118
5119 adev->device.init_check = adev_init_check;
5120 adev->device.set_voice_volume = adev_set_voice_volume;
5121 adev->device.set_master_volume = adev_set_master_volume;
5122 adev->device.get_master_volume = adev_get_master_volume;
5123 adev->device.set_master_mute = adev_set_master_mute;
5124 adev->device.get_master_mute = adev_get_master_mute;
5125 adev->device.set_mode = adev_set_mode;
5126 adev->device.set_mic_mute = adev_set_mic_mute;
5127 adev->device.get_mic_mute = adev_get_mic_mute;
5128 adev->device.set_parameters = adev_set_parameters;
5129 adev->device.get_parameters = adev_get_parameters;
5130 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5131 adev->device.open_output_stream = adev_open_output_stream;
5132 adev->device.close_output_stream = adev_close_output_stream;
5133 adev->device.open_input_stream = adev_open_input_stream;
5134 adev->device.close_input_stream = adev_close_input_stream;
5135 adev->device.dump = adev_dump;
5136
5137 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005138 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005139 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005140 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005143 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005144 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005145 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005146 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005147 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005148 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005149 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005150 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305151 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305152 adev->perf_lock_opts[0] = 0x101;
5153 adev->perf_lock_opts[1] = 0x20E;
5154 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305155
5156 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5157 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005159 adev->platform = platform_init(adev);
5160 if (!adev->platform) {
5161 free(adev->snd_dev_ref_cnt);
5162 free(adev);
5163 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5164 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005165 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305166 pthread_mutex_destroy(&adev->lock);
5167 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005168 return -EINVAL;
5169 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005170
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305171 if (audio_extn_qaf_is_enabled()) {
5172 ret = audio_extn_qaf_init(adev);
5173 if (ret < 0) {
5174 free(adev);
5175 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5176 *device = NULL;
5177 pthread_mutex_unlock(&adev_init_lock);
5178 pthread_mutex_destroy(&adev->lock);
5179 return ret;
5180 }
5181
5182 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5183 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5184 }
5185
Naresh Tanniru4c630392014-05-12 01:05:52 +05305186 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5187
Eric Laurentc4aef752013-09-12 17:45:53 -07005188 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5189 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5190 if (adev->visualizer_lib == NULL) {
5191 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5192 } else {
5193 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5194 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005195 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005196 "visualizer_hal_start_output");
5197 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005198 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005199 "visualizer_hal_stop_output");
5200 }
5201 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305202 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005203 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005204 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005205 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005206
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005207 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5208 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5209 if (adev->offload_effects_lib == NULL) {
5210 ALOGE("%s: DLOPEN failed for %s", __func__,
5211 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5212 } else {
5213 ALOGV("%s: DLOPEN successful for %s", __func__,
5214 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5215 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305216 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005217 "offload_effects_bundle_hal_start_output");
5218 adev->offload_effects_stop_output =
5219 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5220 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005221 adev->offload_effects_set_hpx_state =
5222 (int (*)(bool))dlsym(adev->offload_effects_lib,
5223 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305224 adev->offload_effects_get_parameters =
5225 (void (*)(struct str_parms *, struct str_parms *))
5226 dlsym(adev->offload_effects_lib,
5227 "offload_effects_bundle_get_parameters");
5228 adev->offload_effects_set_parameters =
5229 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5230 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005231 }
5232 }
5233
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005234 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5235 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5236 if (adev->adm_lib == NULL) {
5237 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5238 } else {
5239 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5240 adev->adm_init = (adm_init_t)
5241 dlsym(adev->adm_lib, "adm_init");
5242 adev->adm_deinit = (adm_deinit_t)
5243 dlsym(adev->adm_lib, "adm_deinit");
5244 adev->adm_register_input_stream = (adm_register_input_stream_t)
5245 dlsym(adev->adm_lib, "adm_register_input_stream");
5246 adev->adm_register_output_stream = (adm_register_output_stream_t)
5247 dlsym(adev->adm_lib, "adm_register_output_stream");
5248 adev->adm_deregister_stream = (adm_deregister_stream_t)
5249 dlsym(adev->adm_lib, "adm_deregister_stream");
5250 adev->adm_request_focus = (adm_request_focus_t)
5251 dlsym(adev->adm_lib, "adm_request_focus");
5252 adev->adm_abandon_focus = (adm_abandon_focus_t)
5253 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005254 adev->adm_set_config = (adm_set_config_t)
5255 dlsym(adev->adm_lib, "adm_set_config");
5256 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5257 dlsym(adev->adm_lib, "adm_request_focus_v2");
5258 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5259 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5260 adev->adm_on_routing_change = (adm_on_routing_change_t)
5261 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005262 }
5263 }
5264
Mingming Yin514a8bc2014-07-29 15:22:21 -07005265 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005266 //initialize this to false for now,
5267 //this will be set to true through set param
5268 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005269
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005270 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 *device = &adev->device.common;
5272
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305273 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5274 &adev->streams_output_cfg_list,
5275 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005276
Kiran Kandi910e1862013-10-29 13:29:42 -07005277 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005278
5279 char value[PROPERTY_VALUE_MAX];
5280 int trial;
5281 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5282 trial = atoi(value);
5283 if (period_size_is_plausible_for_low_latency(trial)) {
5284 pcm_config_low_latency.period_size = trial;
5285 pcm_config_low_latency.start_threshold = trial / 4;
5286 pcm_config_low_latency.avail_min = trial / 4;
5287 configured_low_latency_capture_period_size = trial;
5288 }
5289 }
5290 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5291 trial = atoi(value);
5292 if (period_size_is_plausible_for_low_latency(trial)) {
5293 configured_low_latency_capture_period_size = trial;
5294 }
5295 }
5296
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005297 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5298 af_period_multiplier = atoi(value);
5299 if (af_period_multiplier < 0)
5300 af_period_multiplier = 2;
5301 else if (af_period_multiplier > 4)
5302 af_period_multiplier = 4;
5303
5304 ALOGV("new period_multiplier = %d", af_period_multiplier);
5305 }
5306
vivek mehta446c3962015-09-14 10:57:35 -07005307 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005308 pthread_mutex_unlock(&adev_init_lock);
5309
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005310 if (adev->adm_init)
5311 adev->adm_data = adev->adm_init();
5312
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305313 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305314 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005315 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005316 return 0;
5317}
5318
5319static struct hw_module_methods_t hal_module_methods = {
5320 .open = adev_open,
5321};
5322
5323struct audio_module HAL_MODULE_INFO_SYM = {
5324 .common = {
5325 .tag = HARDWARE_MODULE_TAG,
5326 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5327 .hal_api_version = HARDWARE_HAL_API_VERSION,
5328 .id = AUDIO_HARDWARE_MODULE_ID,
5329 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005330 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331 .methods = &hal_module_methods,
5332 },
5333};