blob: b61c12d1952ecbff9fbad3cbb2994b138d461729 [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];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301026 snd_device_t uc_derive_snd_device;
1027 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001028 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001029 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301030 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 /*
1032 * This function is to make sure that all the usecases that are active on
1033 * the hardware codec backend are always routed to any one device that is
1034 * handled by the hardware codec.
1035 * For example, if low-latency and deep-buffer usecases are currently active
1036 * on speaker and out_set_parameters(headset) is received on low-latency
1037 * output, then we have to make sure deep-buffer is also switched to headset,
1038 * because of the limitation that both the devices cannot be enabled
1039 * at the same time as they share the same backend.
1040 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001041 /*
1042 * This call is to check if we need to force routing for a particular stream
1043 * If there is a backend configuration change for the device when a
1044 * new stream starts, then ADM needs to be closed and re-opened with the new
1045 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001046 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001047 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001048 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1049 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301050 /* For a2dp device reconfigure all active sessions
1051 * with new AFE encoder format based on a2dp state
1052 */
1053 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1054 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1055 audio_extn_a2dp_is_force_device_switch()) {
1056 force_routing = true;
1057 force_restart_session = true;
1058 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301059 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1060
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001062 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001063 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001064 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1065 switch_device[i] = false;
1066
1067 list_for_each(node, &adev->usecase_list) {
1068 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001069
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301070 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1071 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301072 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301073 platform_get_snd_device_name(usecase->out_snd_device),
1074 platform_check_backends_match(snd_device, usecase->out_snd_device));
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301075 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1076 usecase, uc_info, snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001077 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301078 usecase != uc_info &&
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301079 ((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301080 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1081 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301082 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301083 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1084 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1085 ((force_restart_session) ||
1086 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301087
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301088 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1089 __func__, use_case_table[usecase->id],
1090 platform_get_snd_device_name(usecase->out_snd_device));
1091 disable_audio_route(adev, usecase);
1092 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301093 /* Enable existing usecase on derived playback device */
1094 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301095 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 }
1097 }
1098
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301099 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1100 num_uc_to_switch);
1101
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001103 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301105 /* Make sure the previous devices to be disabled first and then enable the
1106 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 list_for_each(node, &adev->usecase_list) {
1108 usecase = node_to_item(node, struct audio_usecase, list);
1109 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001110 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 }
1112 }
1113
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001114 list_for_each(node, &adev->usecase_list) {
1115 usecase = node_to_item(node, struct audio_usecase, list);
1116 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301117 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001118 }
1119 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 /* Re-route all the usecases on the shared backend other than the
1122 specified usecase to new snd devices */
1123 list_for_each(node, &adev->usecase_list) {
1124 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301125 /* Update the out_snd_device only before enabling the audio route */
1126 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301127 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301128 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301129 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301130 use_case_table[usecase->id],
1131 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001132 /* Update voc calibration before enabling VoIP route */
1133 if (usecase->type == VOIP_CALL)
1134 status = platform_switch_voice_call_device_post(adev->platform,
1135 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001136 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301137 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301138 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 }
1140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 }
1142}
1143
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301144static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001145 struct audio_usecase *uc_info,
1146 snd_device_t snd_device)
1147{
1148 struct listnode *node;
1149 struct audio_usecase *usecase;
1150 bool switch_device[AUDIO_USECASE_MAX];
1151 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301152 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001153 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001154
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301155 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1156 snd_device);
1157 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301158
1159 /*
1160 * Make sure out devices is checked against out codec backend device and
1161 * also in devices against in codec backend. Checking out device against in
1162 * codec backend or vice versa causes issues.
1163 */
1164 if (uc_info->type == PCM_CAPTURE)
1165 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001166 /*
1167 * This function is to make sure that all the active capture usecases
1168 * are always routed to the same input sound device.
1169 * For example, if audio-record and voice-call usecases are currently
1170 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1171 * is received for voice call then we have to make sure that audio-record
1172 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1173 * because of the limitation that two devices cannot be enabled
1174 * at the same time if they share the same backend.
1175 */
1176 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1177 switch_device[i] = false;
1178
1179 list_for_each(node, &adev->usecase_list) {
1180 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301181 /*
1182 * TODO: Enhance below condition to handle BT sco/USB multi recording
1183 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001184 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301186 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301187 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301188 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001189 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001190 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1192 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001193 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001194 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001195 switch_device[usecase->id] = true;
1196 num_uc_to_switch++;
1197 }
1198 }
1199
1200 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001201 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001202
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301203 /* Make sure the previous devices to be disabled first and then enable the
1204 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001205 list_for_each(node, &adev->usecase_list) {
1206 usecase = node_to_item(node, struct audio_usecase, list);
1207 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001208 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001209 }
1210 }
1211
1212 list_for_each(node, &adev->usecase_list) {
1213 usecase = node_to_item(node, struct audio_usecase, list);
1214 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001215 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216 }
1217 }
1218
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001219 /* Re-route all the usecases on the shared backend other than the
1220 specified usecase to new snd devices */
1221 list_for_each(node, &adev->usecase_list) {
1222 usecase = node_to_item(node, struct audio_usecase, list);
1223 /* Update the in_snd_device only before enabling the audio route */
1224 if (switch_device[usecase->id] ) {
1225 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001226 if (usecase->type != VOICE_CALL) {
1227 /* Update voc calibration before enabling VoIP route */
1228 if (usecase->type == VOIP_CALL)
1229 status = platform_switch_voice_call_device_post(adev->platform,
1230 usecase->out_snd_device,
1231 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301232 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001233 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001234 }
1235 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001236 }
1237}
1238
Mingming Yin3a941d42016-02-17 18:08:05 -08001239static void reset_hdmi_sink_caps(struct stream_out *out) {
1240 int i = 0;
1241
1242 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1243 out->supported_channel_masks[i] = 0;
1244 }
1245 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1246 out->supported_formats[i] = 0;
1247 }
1248 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1249 out->supported_sample_rates[i] = 0;
1250 }
1251}
1252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001254static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001255{
Mingming Yin3a941d42016-02-17 18:08:05 -08001256 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001257 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258
Mingming Yin3a941d42016-02-17 18:08:05 -08001259 reset_hdmi_sink_caps(out);
1260
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001261 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001262 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001263 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001264 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001265 }
1266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001269 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001270 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001271 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1272 case 6:
1273 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1274 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1275 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1276 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1277 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1278 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 break;
1280 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001281 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001282 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283 break;
1284 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001285
1286 // check channel format caps
1287 i = 0;
1288 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1289 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1290 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1291 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1292 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1293 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1294 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1295 }
1296
1297 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1298 ALOGV(":%s HDMI supports DTS format", __func__);
1299 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1300 }
1301
1302 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1303 ALOGV(":%s HDMI supports DTS HD format", __func__);
1304 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1305 }
1306
1307
1308 // check sample rate caps
1309 i = 0;
1310 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1311 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1312 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1313 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1314 }
1315 }
1316
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001317 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318}
1319
Alexy Josephb1379942016-01-29 15:49:38 -08001320audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001321 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001322{
1323 struct audio_usecase *usecase;
1324 struct listnode *node;
1325
1326 list_for_each(node, &adev->usecase_list) {
1327 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001328 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001329 ALOGV("%s: usecase id %d", __func__, usecase->id);
1330 return usecase->id;
1331 }
1332 }
1333 return USECASE_INVALID;
1334}
1335
Alexy Josephb1379942016-01-29 15:49:38 -08001336struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001337 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338{
1339 struct audio_usecase *usecase;
1340 struct listnode *node;
1341
1342 list_for_each(node, &adev->usecase_list) {
1343 usecase = node_to_item(node, struct audio_usecase, list);
1344 if (usecase->id == uc_id)
1345 return usecase;
1346 }
1347 return NULL;
1348}
1349
Dhananjay Kumard4833242016-10-06 22:09:12 +05301350struct stream_in *get_next_active_input(const struct audio_device *adev)
1351{
1352 struct audio_usecase *usecase;
1353 struct listnode *node;
1354
1355 list_for_each_reverse(node, &adev->usecase_list) {
1356 usecase = node_to_item(node, struct audio_usecase, list);
1357 if (usecase->type == PCM_CAPTURE)
1358 return usecase->stream.in;
1359 }
1360 return NULL;
1361}
1362
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301363/*
1364 * is a true native playback active
1365 */
1366bool audio_is_true_native_stream_active(struct audio_device *adev)
1367{
1368 bool active = false;
1369 int i = 0;
1370 struct listnode *node;
1371
1372 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1373 ALOGV("%s:napb: not in true mode or non hdphones device",
1374 __func__);
1375 active = false;
1376 goto exit;
1377 }
1378
1379 list_for_each(node, &adev->usecase_list) {
1380 struct audio_usecase *uc;
1381 uc = node_to_item(node, struct audio_usecase, list);
1382 struct stream_out *curr_out =
1383 (struct stream_out*) uc->stream.out;
1384
1385 if (curr_out && PCM_PLAYBACK == uc->type) {
1386 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1387 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1388 uc->id, curr_out->sample_rate,
1389 curr_out->bit_width,
1390 platform_get_snd_device_name(uc->out_snd_device));
1391
1392 if (is_offload_usecase(uc->id) &&
1393 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1394 active = true;
1395 ALOGD("%s:napb:native stream detected", __func__);
1396 }
1397 }
1398 }
1399exit:
1400 return active;
1401}
1402
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301403/*
1404 * if native DSD playback active
1405 */
1406bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1407{
1408 bool active = false;
1409 struct listnode *node = NULL;
1410 struct audio_usecase *uc = NULL;
1411 struct stream_out *curr_out = NULL;
1412
1413 list_for_each(node, &adev->usecase_list) {
1414 uc = node_to_item(node, struct audio_usecase, list);
1415 curr_out = (struct stream_out*) uc->stream.out;
1416
1417 if (curr_out && PCM_PLAYBACK == uc->type &&
1418 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1419 active = true;
1420 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301421 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301422 }
1423 }
1424 return active;
1425}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301426
1427static bool force_device_switch(struct audio_usecase *usecase)
1428{
1429 bool ret = false;
1430 bool is_it_true_mode = false;
1431
1432 if (is_offload_usecase(usecase->id) &&
1433 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001434 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1435 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1436 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301437 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1438 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1439 (!is_it_true_mode && adev->native_playback_enabled)){
1440 ret = true;
1441 ALOGD("napb: time to toggle native mode");
1442 }
1443 }
1444
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301445 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301446 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1447 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301448 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001449 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301450 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301451 ALOGD("Force a2dp device switch to update new encoder config");
1452 ret = true;
1453 }
1454
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301455 return ret;
1456}
1457
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001458int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001460 snd_device_t out_snd_device = SND_DEVICE_NONE;
1461 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 struct audio_usecase *usecase = NULL;
1463 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001464 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001465 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001466 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301469 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1470
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471 usecase = get_usecase_from_list(adev, uc_id);
1472 if (usecase == NULL) {
1473 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1474 return -EINVAL;
1475 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001477 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001478 (usecase->type == VOIP_CALL) ||
1479 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301480 if(usecase->stream.out == NULL) {
1481 ALOGE("%s: stream.out is NULL", __func__);
1482 return -EINVAL;
1483 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001484 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001485 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001486 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487 usecase->devices = usecase->stream.out->devices;
1488 } else {
1489 /*
1490 * If the voice call is active, use the sound devices of voice call usecase
1491 * so that it would not result any device switch. All the usecases will
1492 * be switched to new device when select_devices() is called for voice call
1493 * usecase. This is to avoid switching devices for voice call when
1494 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001495 * choose voice call device only if the use case device is
1496 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001498 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001499 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001500 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001501 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1502 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301503 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1504 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001505 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 in_snd_device = vc_usecase->in_snd_device;
1507 out_snd_device = vc_usecase->out_snd_device;
1508 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001509 } else if (voice_extn_compress_voip_is_active(adev)) {
1510 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001511 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001512 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1513 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001514 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001515 in_snd_device = voip_usecase->in_snd_device;
1516 out_snd_device = voip_usecase->out_snd_device;
1517 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001518 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001519 hfp_ucid = audio_extn_hfp_get_usecase();
1520 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001521 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001522 in_snd_device = hfp_usecase->in_snd_device;
1523 out_snd_device = hfp_usecase->out_snd_device;
1524 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 }
1526 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301527 if (usecase->stream.out == NULL) {
1528 ALOGE("%s: stream.out is NULL", __func__);
1529 return -EINVAL;
1530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531 usecase->devices = usecase->stream.out->devices;
1532 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001533 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001534 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001535 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001536 if (usecase->stream.out == adev->primary_output &&
1537 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001538 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001539 select_devices(adev, adev->active_input->usecase);
1540 }
1541 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301543 if (usecase->stream.in == NULL) {
1544 ALOGE("%s: stream.in is NULL", __func__);
1545 return -EINVAL;
1546 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001547 usecase->devices = usecase->stream.in->device;
1548 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001549 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001550 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001551 if (adev->active_input &&
1552 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301553 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1554 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1555 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001556 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001557 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001558 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1559 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001560 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001561 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 }
1564 }
1565
1566 if (out_snd_device == usecase->out_snd_device &&
1567 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301568
1569 if (!force_device_switch(usecase))
1570 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 }
1572
sangwoobc677242013-08-08 16:53:43 +09001573 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001574 out_snd_device, platform_get_snd_device_name(out_snd_device),
1575 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 /*
1578 * Limitation: While in call, to do a device switch we need to disable
1579 * and enable both RX and TX devices though one of them is same as current
1580 * device.
1581 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001582 if ((usecase->type == VOICE_CALL) &&
1583 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1584 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001585 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001586 }
1587
1588 if (((usecase->type == VOICE_CALL) ||
1589 (usecase->type == VOIP_CALL)) &&
1590 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1591 /* Disable sidetone only if voice/voip call already exists */
1592 if (voice_is_call_state_active(adev) ||
1593 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001594 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001595
1596 /* Disable aanc only if voice call exists */
1597 if (voice_is_call_state_active(adev))
1598 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001599 }
1600
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 /* Disable current sound devices */
1602 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001603 disable_audio_route(adev, usecase);
1604 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 }
1606
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001607 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001608 disable_audio_route(adev, usecase);
1609 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610 }
1611
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001612 /* Applicable only on the targets that has external modem.
1613 * New device information should be sent to modem before enabling
1614 * the devices to reduce in-call device switch time.
1615 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001616 if ((usecase->type == VOICE_CALL) &&
1617 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1618 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001619 status = platform_switch_voice_call_enable_device_config(adev->platform,
1620 out_snd_device,
1621 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001622 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001623
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624 /* Enable new sound devices */
1625 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001626 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001627 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628 }
1629
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001630 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301631 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001632 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001633 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001634
Avinash Vaish71a8b972014-07-24 15:36:33 +05301635 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001636 status = platform_switch_voice_call_device_post(adev->platform,
1637 out_snd_device,
1638 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301639 enable_audio_route_for_voice_usecases(adev, usecase);
1640 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001641
sangwoo170731f2013-06-08 15:36:36 +09001642 usecase->in_snd_device = in_snd_device;
1643 usecase->out_snd_device = out_snd_device;
1644
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301645 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1646 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301647 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001648 if ((24 == usecase->stream.out->bit_width) &&
1649 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1650 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1651 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1652 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1653 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1654 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1655 /*
1656 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1657 * configured device sample rate, if not update the COPP rate to be equal to the
1658 * device sample rate, else open COPP at stream sample rate
1659 */
1660 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1661 usecase->stream.out->sample_rate,
1662 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301663 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1664 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001665 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1666 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1667 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1668 }
1669
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001670 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001671 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001672 audio_extn_gef_notify_device_config(
1673 usecase->stream.out->devices,
1674 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001675 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001676 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001677 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301678 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001679 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001680
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001681 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001682 /* Enable aanc only if voice call exists */
1683 if (voice_is_call_state_active(adev))
1684 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1685
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001686 /* Enable sidetone only if other voice/voip call already exists */
1687 if (voice_is_call_state_active(adev) ||
1688 voice_extn_compress_voip_is_started(adev))
1689 voice_set_sidetone(adev, out_snd_device, true);
1690 }
1691
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001692 /* Applicable only on the targets that has external modem.
1693 * Enable device command should be sent to modem only after
1694 * enabling voice call mixer controls
1695 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001696 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001697 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1698 out_snd_device,
1699 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301700 ALOGD("%s: done",__func__);
1701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 return status;
1703}
1704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705static int stop_input_stream(struct stream_in *in)
1706{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301707 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 struct audio_usecase *uc_info;
1709 struct audio_device *adev = in->dev;
1710
Eric Laurent994a6932013-07-17 11:51:42 -07001711 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 uc_info = get_usecase_from_list(adev, in->usecase);
1714 if (uc_info == NULL) {
1715 ALOGE("%s: Could not find the usecase (%d) in the list",
1716 __func__, in->usecase);
1717 return -EINVAL;
1718 }
1719
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001720 /* Close in-call recording streams */
1721 voice_check_and_stop_incall_rec_usecase(adev, in);
1722
Eric Laurent150dbfe2013-02-27 14:31:02 -08001723 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001724 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725
1726 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001727 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001729 list_remove(&uc_info->list);
1730 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001732 adev->active_input = get_next_active_input(adev);
1733
Eric Laurent994a6932013-07-17 11:51:42 -07001734 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735 return ret;
1736}
1737
1738int start_input_stream(struct stream_in *in)
1739{
1740 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001741 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 struct audio_usecase *uc_info;
1743 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301744 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745
Mingming Yin2664a5b2015-09-03 10:53:11 -07001746 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1747 if (get_usecase_from_list(adev, usecase) == NULL)
1748 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301749 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1750 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001751
Naresh Tanniru80659832014-06-04 18:17:56 +05301752
1753 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301754 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301755 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301756 goto error_config;
1757 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301758
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001759 /* Check if source matches incall recording usecase criteria */
1760 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1761 if (ret)
1762 goto error_config;
1763 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001764 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1765
1766 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1767 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1768 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001769 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001770 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001771
Eric Laurentb23d5282013-05-14 15:27:20 -07001772 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 if (in->pcm_device_id < 0) {
1774 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1775 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001776 ret = -EINVAL;
1777 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001779
1780 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001782
1783 if (!uc_info) {
1784 ret = -ENOMEM;
1785 goto error_config;
1786 }
1787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 uc_info->id = in->usecase;
1789 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001790 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001791 uc_info->devices = in->device;
1792 uc_info->in_snd_device = SND_DEVICE_NONE;
1793 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001795 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301796 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1797 adev->perf_lock_opts,
1798 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001799 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301801 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1802 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001803
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301804 if (audio_extn_cin_attached_usecase(in->usecase)) {
1805 ret = audio_extn_cin_start_input_stream(in);
1806 if (ret)
1807 goto error_open;
1808 else
1809 goto done_open;
1810 }
1811
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001812 unsigned int flags = PCM_IN;
1813 unsigned int pcm_open_retry_count = 0;
1814
1815 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1816 flags |= PCM_MMAP | PCM_NOIRQ;
1817 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001818 } else if (in->realtime) {
1819 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001820 }
1821
1822 while (1) {
1823 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1824 flags, &in->config);
1825 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1826 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1827 if (in->pcm != NULL) {
1828 pcm_close(in->pcm);
1829 in->pcm = NULL;
1830 }
1831 if (pcm_open_retry_count-- == 0) {
1832 ret = -EIO;
1833 goto error_open;
1834 }
1835 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1836 continue;
1837 }
1838 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001840
1841 ALOGV("%s: pcm_prepare", __func__);
1842 ret = pcm_prepare(in->pcm);
1843 if (ret < 0) {
1844 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1845 pcm_close(in->pcm);
1846 in->pcm = NULL;
1847 goto error_open;
1848 }
1849
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001850 register_in_stream(in);
1851 if (in->realtime) {
1852 ret = pcm_start(in->pcm);
1853 if (ret < 0)
1854 goto error_open;
1855 }
1856
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301857done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301858 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001859 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001860
Eric Laurentc8400632013-02-14 19:04:54 -08001861 return ret;
1862
1863error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301864 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001866error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301867 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301868 /*
1869 * sleep 50ms to allow sufficient time for kernel
1870 * drivers to recover incases like SSR.
1871 */
1872 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001874
1875 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876}
1877
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001878void lock_input_stream(struct stream_in *in)
1879{
1880 pthread_mutex_lock(&in->pre_lock);
1881 pthread_mutex_lock(&in->lock);
1882 pthread_mutex_unlock(&in->pre_lock);
1883}
1884
1885void lock_output_stream(struct stream_out *out)
1886{
1887 pthread_mutex_lock(&out->pre_lock);
1888 pthread_mutex_lock(&out->lock);
1889 pthread_mutex_unlock(&out->pre_lock);
1890}
1891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892/* must be called with out->lock locked */
1893static int send_offload_cmd_l(struct stream_out* out, int command)
1894{
1895 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1896
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001897 if (!cmd) {
1898 ALOGE("failed to allocate mem for command 0x%x", command);
1899 return -ENOMEM;
1900 }
1901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001902 ALOGVV("%s %d", __func__, command);
1903
1904 cmd->cmd = command;
1905 list_add_tail(&out->offload_cmd_list, &cmd->node);
1906 pthread_cond_signal(&out->offload_cond);
1907 return 0;
1908}
1909
1910/* must be called iwth out->lock locked */
1911static void stop_compressed_output_l(struct stream_out *out)
1912{
1913 out->offload_state = OFFLOAD_STATE_IDLE;
1914 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001915 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001916 if (out->compr != NULL) {
1917 compress_stop(out->compr);
1918 while (out->offload_thread_blocked) {
1919 pthread_cond_wait(&out->cond, &out->lock);
1920 }
1921 }
1922}
1923
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001924bool is_offload_usecase(audio_usecase_t uc_id)
1925{
1926 unsigned int i;
1927 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1928 if (uc_id == offload_usecases[i])
1929 return true;
1930 }
1931 return false;
1932}
1933
vivek mehta446c3962015-09-14 10:57:35 -07001934static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001935{
vivek mehta446c3962015-09-14 10:57:35 -07001936 audio_usecase_t ret_uc = USECASE_INVALID;
1937 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001938 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001939 if (!adev->multi_offload_enable) {
1940 if (is_direct_pcm)
1941 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1942 else
1943 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001944
vivek mehta446c3962015-09-14 10:57:35 -07001945 pthread_mutex_lock(&adev->lock);
1946 if (get_usecase_from_list(adev, ret_uc) != NULL)
1947 ret_uc = USECASE_INVALID;
1948 pthread_mutex_unlock(&adev->lock);
1949
1950 return ret_uc;
1951 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001952
1953 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001954 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1955 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1956 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1957 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001958 break;
1959 }
1960 }
vivek mehta446c3962015-09-14 10:57:35 -07001961
1962 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1963 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001964}
1965
1966static void free_offload_usecase(struct audio_device *adev,
1967 audio_usecase_t uc_id)
1968{
vivek mehta446c3962015-09-14 10:57:35 -07001969 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001970 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001971
1972 if (!adev->multi_offload_enable)
1973 return;
1974
1975 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1976 if (offload_usecases[offload_uc_index] == uc_id) {
1977 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001978 break;
1979 }
1980 }
1981 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1982}
1983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984static void *offload_thread_loop(void *context)
1985{
1986 struct stream_out *out = (struct stream_out *) context;
1987 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001988 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001989
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1991 set_sched_policy(0, SP_FOREGROUND);
1992 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1993
1994 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001995 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996 for (;;) {
1997 struct offload_cmd *cmd = NULL;
1998 stream_callback_event_t event;
1999 bool send_callback = false;
2000
2001 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2002 __func__, list_empty(&out->offload_cmd_list),
2003 out->offload_state);
2004 if (list_empty(&out->offload_cmd_list)) {
2005 ALOGV("%s SLEEPING", __func__);
2006 pthread_cond_wait(&out->offload_cond, &out->lock);
2007 ALOGV("%s RUNNING", __func__);
2008 continue;
2009 }
2010
2011 item = list_head(&out->offload_cmd_list);
2012 cmd = node_to_item(item, struct offload_cmd, node);
2013 list_remove(item);
2014
2015 ALOGVV("%s STATE %d CMD %d out->compr %p",
2016 __func__, out->offload_state, cmd->cmd, out->compr);
2017
2018 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2019 free(cmd);
2020 break;
2021 }
2022
2023 if (out->compr == NULL) {
2024 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002025 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 pthread_cond_signal(&out->cond);
2027 continue;
2028 }
2029 out->offload_thread_blocked = true;
2030 pthread_mutex_unlock(&out->lock);
2031 send_callback = false;
2032 switch(cmd->cmd) {
2033 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002034 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002036 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 send_callback = true;
2038 event = STREAM_CBK_EVENT_WRITE_READY;
2039 break;
2040 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002041 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302042 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002043 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302044 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002045 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302046 if (ret < 0)
2047 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302048 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302049 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002050 compress_drain(out->compr);
2051 else
2052 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302053 if (ret != -ENETRESET) {
2054 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302055 pthread_mutex_lock(&out->lock);
2056 out->send_new_metadata = 1;
2057 out->send_next_track_params = true;
2058 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302059 event = STREAM_CBK_EVENT_DRAIN_READY;
2060 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2061 } else
2062 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 break;
2064 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002065 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002067 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 send_callback = true;
2069 event = STREAM_CBK_EVENT_DRAIN_READY;
2070 break;
2071 default:
2072 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2073 break;
2074 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002075 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 out->offload_thread_blocked = false;
2077 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002078 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002079 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002081 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 free(cmd);
2083 }
2084
2085 pthread_cond_signal(&out->cond);
2086 while (!list_empty(&out->offload_cmd_list)) {
2087 item = list_head(&out->offload_cmd_list);
2088 list_remove(item);
2089 free(node_to_item(item, struct offload_cmd, node));
2090 }
2091 pthread_mutex_unlock(&out->lock);
2092
2093 return NULL;
2094}
2095
2096static int create_offload_callback_thread(struct stream_out *out)
2097{
2098 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2099 list_init(&out->offload_cmd_list);
2100 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2101 offload_thread_loop, out);
2102 return 0;
2103}
2104
2105static int destroy_offload_callback_thread(struct stream_out *out)
2106{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002107 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 stop_compressed_output_l(out);
2109 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2110
2111 pthread_mutex_unlock(&out->lock);
2112 pthread_join(out->offload_thread, (void **) NULL);
2113 pthread_cond_destroy(&out->offload_cond);
2114
2115 return 0;
2116}
2117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118static int stop_output_stream(struct stream_out *out)
2119{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302120 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 struct audio_usecase *uc_info;
2122 struct audio_device *adev = out->dev;
2123
Eric Laurent994a6932013-07-17 11:51:42 -07002124 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002125 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 uc_info = get_usecase_from_list(adev, out->usecase);
2127 if (uc_info == NULL) {
2128 ALOGE("%s: Could not find the usecase (%d) in the list",
2129 __func__, out->usecase);
2130 return -EINVAL;
2131 }
2132
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002133 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302134 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002135 if (adev->visualizer_stop_output != NULL)
2136 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002137
2138 audio_extn_dts_remove_state_notifier_node(out->usecase);
2139
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002140 if (adev->offload_effects_stop_output != NULL)
2141 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2142 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002143
Eric Laurent150dbfe2013-02-27 14:31:02 -08002144 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002145 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002146
2147 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002148 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002150 list_remove(&uc_info->list);
2151 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002153 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302154 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002155 ALOGV("Disable passthrough , reset mixer to pcm");
2156 /* NO_PASSTHROUGH */
2157 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002158 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002159 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2160 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002161
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302162 /* Must be called after removing the usecase from list */
2163 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302164 audio_extn_keep_alive_start();
2165
Eric Laurent994a6932013-07-17 11:51:42 -07002166 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 return ret;
2168}
2169
2170int start_output_stream(struct stream_out *out)
2171{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 struct audio_usecase *uc_info;
2174 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302175 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002176 char mixer_ctl_name[128];
2177 struct mixer_ctl *ctl = NULL;
2178 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002180 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2181 ret = -EINVAL;
2182 goto error_config;
2183 }
2184
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302185 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2186 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2187 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302188
Naresh Tanniru80659832014-06-04 18:17:56 +05302189 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302190 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302191 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302192 goto error_config;
2193 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302194
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302195 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2196 if (!audio_extn_a2dp_is_ready()) {
2197 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2198 //combo usecase just by pass a2dp
2199 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2200 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2201 } else {
2202 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2203 ret = -EAGAIN;
2204 goto error_config;
2205 }
2206 }
2207 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002208 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 if (out->pcm_device_id < 0) {
2210 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2211 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002212 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002213 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 }
2215
2216 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002217
2218 if (!uc_info) {
2219 ret = -ENOMEM;
2220 goto error_config;
2221 }
2222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 uc_info->id = out->usecase;
2224 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002225 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226 uc_info->devices = out->devices;
2227 uc_info->in_snd_device = SND_DEVICE_NONE;
2228 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002229 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302231 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2232 adev->perf_lock_opts,
2233 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302234
2235 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2236 audio_extn_keep_alive_stop();
2237 if (audio_extn_passthru_is_enabled() &&
2238 audio_extn_passthru_is_passthrough_stream(out)) {
2239 audio_extn_passthru_on_start(out);
2240 audio_extn_passthru_update_stream_configuration(adev, out);
2241 }
2242 }
2243
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002244 select_devices(adev, out->usecase);
2245
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002246 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2247 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002248 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002249 unsigned int flags = PCM_OUT;
2250 unsigned int pcm_open_retry_count = 0;
2251 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2252 flags |= PCM_MMAP | PCM_NOIRQ;
2253 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002254 } else if (out->realtime) {
2255 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002256 } else
2257 flags |= PCM_MONOTONIC;
2258
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002259 if ((adev->vr_audio_mode_enabled) &&
2260 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2261 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2262 "PCM_Dev %d Topology", out->pcm_device_id);
2263 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2264 if (!ctl) {
2265 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2266 __func__, mixer_ctl_name);
2267 } else {
2268 //if success use ULLPP
2269 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2270 __func__, mixer_ctl_name, out->pcm_device_id);
2271 //There is a still a possibility that some sessions
2272 // that request for FAST|RAW when 3D audio is active
2273 //can go through ULLPP. Ideally we expects apps to
2274 //listen to audio focus and stop concurrent playback
2275 //Also, we will look for mode flag (voice_in_communication)
2276 //before enabling the realtime flag.
2277 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2278 }
2279 }
2280
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002281 while (1) {
2282 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2283 flags, &out->config);
2284 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2285 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2286 if (out->pcm != NULL) {
2287 pcm_close(out->pcm);
2288 out->pcm = NULL;
2289 }
2290 if (pcm_open_retry_count-- == 0) {
2291 ret = -EIO;
2292 goto error_open;
2293 }
2294 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2295 continue;
2296 }
2297 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002299
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002300 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2301 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002302
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002303 ALOGV("%s: pcm_prepare", __func__);
2304 if (pcm_is_ready(out->pcm)) {
2305 ret = pcm_prepare(out->pcm);
2306 if (ret < 0) {
2307 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2308 pcm_close(out->pcm);
2309 out->pcm = NULL;
2310 goto error_open;
2311 }
2312 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002314 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2315 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002317 out->compr = compress_open(adev->snd_card,
2318 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002319 COMPRESS_IN, &out->compr_config);
2320 if (out->compr && !is_compress_ready(out->compr)) {
2321 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2322 compress_close(out->compr);
2323 out->compr = NULL;
2324 ret = -EIO;
2325 goto error_open;
2326 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302327 /* compress_open sends params of the track, so reset the flag here */
2328 out->is_compr_metadata_avail = false;
2329
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330 if (out->offload_callback)
2331 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002332
Fred Oh3f43e742015-03-04 18:42:34 -08002333 /* Since small bufs uses blocking writes, a write will be blocked
2334 for the default max poll time (20s) in the event of an SSR.
2335 Reduce the poll time to observe and deal with SSR faster.
2336 */
Ashish Jain5106d362016-05-11 19:23:33 +05302337 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002338 compress_set_max_poll_wait(out->compr, 1000);
2339 }
2340
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002341 audio_extn_dts_create_state_notifier_node(out->usecase);
2342 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2343 popcount(out->channel_mask),
2344 out->playback_started);
2345
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002346#ifdef DS1_DOLBY_DDP_ENABLED
2347 if (audio_extn_is_dolby_format(out->format))
2348 audio_extn_dolby_send_ddp_endp_params(adev);
2349#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302350 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2351 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002352 if (adev->visualizer_start_output != NULL)
2353 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2354 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302355 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002356 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002357 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002359
2360 if (ret == 0) {
2361 register_out_stream(out);
2362 if (out->realtime) {
2363 ret = pcm_start(out->pcm);
2364 if (ret < 0)
2365 goto error_open;
2366 }
2367 }
2368
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302369 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002370 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002371
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002372 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302374 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002376error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302377 /*
2378 * sleep 50ms to allow sufficient time for kernel
2379 * drivers to recover incases like SSR.
2380 */
2381 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002382 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383}
2384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385static int check_input_parameters(uint32_t sample_rate,
2386 audio_format_t format,
2387 int channel_count)
2388{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002389 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302391 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2392 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2393 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002394 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302395 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002396
2397 switch (channel_count) {
2398 case 1:
2399 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302400 case 3:
2401 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002402 case 6:
2403 break;
2404 default:
2405 ret = -EINVAL;
2406 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407
2408 switch (sample_rate) {
2409 case 8000:
2410 case 11025:
2411 case 12000:
2412 case 16000:
2413 case 22050:
2414 case 24000:
2415 case 32000:
2416 case 44100:
2417 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302418 case 96000:
2419 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 break;
2421 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002422 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 }
2424
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002425 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426}
2427
2428static size_t get_input_buffer_size(uint32_t sample_rate,
2429 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002430 int channel_count,
2431 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 size_t size = 0;
2434
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002435 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2436 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002438 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002439 if (is_low_latency)
2440 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302441
2442 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002444 /* make sure the size is multiple of 32 bytes
2445 * At 48 kHz mono 16-bit PCM:
2446 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2447 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2448 */
2449 size += 0x1f;
2450 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002451
2452 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453}
2454
Ashish Jain058165c2016-09-28 23:18:48 +05302455static size_t get_output_period_size(uint32_t sample_rate,
2456 audio_format_t format,
2457 int channel_count,
2458 int duration /*in millisecs*/)
2459{
2460 size_t size = 0;
2461 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2462
2463 if ((duration == 0) || (sample_rate == 0) ||
2464 (bytes_per_sample == 0) || (channel_count == 0)) {
2465 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2466 bytes_per_sample, channel_count);
2467 return -EINVAL;
2468 }
2469
2470 size = (sample_rate *
2471 duration *
2472 bytes_per_sample *
2473 channel_count) / 1000;
2474 /*
2475 * To have same PCM samples for all channels, the buffer size requires to
2476 * be multiple of (number of channels * bytes per sample)
2477 * For writes to succeed, the buffer must be written at address which is multiple of 32
2478 */
2479 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2480
2481 return (size/(channel_count * bytes_per_sample));
2482}
2483
Ashish Jain5106d362016-05-11 19:23:33 +05302484static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2485{
2486 uint64_t actual_frames_rendered = 0;
2487 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2488
2489 /* This adjustment accounts for buffering after app processor.
2490 * It is based on estimated DSP latency per use case, rather than exact.
2491 */
2492 int64_t platform_latency = platform_render_latency(out->usecase) *
2493 out->sample_rate / 1000000LL;
2494
2495 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2496 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2497 * hence only estimate.
2498 */
2499 int64_t signed_frames = out->written - kernel_buffer_size;
2500
2501 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2502
2503 if (signed_frames > 0)
2504 actual_frames_rendered = signed_frames;
2505
2506 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2507 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2508 (long long int)out->written, (int)kernel_buffer_size,
2509 audio_bytes_per_sample(out->compr_config.codec->format),
2510 popcount(out->channel_mask));
2511
2512 return actual_frames_rendered;
2513}
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2516{
2517 struct stream_out *out = (struct stream_out *)stream;
2518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520}
2521
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002522static int out_set_sample_rate(struct audio_stream *stream __unused,
2523 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524{
2525 return -ENOSYS;
2526}
2527
2528static size_t out_get_buffer_size(const struct audio_stream *stream)
2529{
2530 struct stream_out *out = (struct stream_out *)stream;
2531
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002532 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002534 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2535 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302536 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302537 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002538
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002539 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002540 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541}
2542
2543static uint32_t out_get_channels(const struct audio_stream *stream)
2544{
2545 struct stream_out *out = (struct stream_out *)stream;
2546
2547 return out->channel_mask;
2548}
2549
2550static audio_format_t out_get_format(const struct audio_stream *stream)
2551{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 struct stream_out *out = (struct stream_out *)stream;
2553
2554 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555}
2556
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002557static int out_set_format(struct audio_stream *stream __unused,
2558 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559{
2560 return -ENOSYS;
2561}
2562
2563static int out_standby(struct audio_stream *stream)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302568 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2569 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002571 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002573 if (adev->adm_deregister_stream)
2574 adev->adm_deregister_stream(adev->adm_data, out->handle);
2575
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002576 if (is_offload_usecase(out->usecase))
2577 stop_compressed_output_l(out);
2578
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002579 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002581 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2582 voice_extn_compress_voip_close_output_stream(stream);
2583 pthread_mutex_unlock(&adev->lock);
2584 pthread_mutex_unlock(&out->lock);
2585 ALOGD("VOIP output entered standby");
2586 return 0;
2587 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588 if (out->pcm) {
2589 pcm_close(out->pcm);
2590 out->pcm = NULL;
2591 }
2592 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002593 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302594 out->send_next_track_params = false;
2595 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002596 out->gapless_mdata.encoder_delay = 0;
2597 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 if (out->compr != NULL) {
2599 compress_close(out->compr);
2600 out->compr = NULL;
2601 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002604 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 }
2606 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302607 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 return 0;
2609}
2610
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002611static int out_dump(const struct audio_stream *stream __unused,
2612 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613{
2614 return 0;
2615}
2616
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002617static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2618{
2619 int ret = 0;
2620 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002621
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002622 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002623 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002624 return -EINVAL;
2625 }
2626
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302627 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002628
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002629 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2630 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302631 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002632 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002633 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2634 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302635 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002636 }
2637
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002638 ALOGV("%s new encoder delay %u and padding %u", __func__,
2639 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2640
2641 return 0;
2642}
2643
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002644static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2645{
2646 return out == adev->primary_output || out == adev->voice_tx_output;
2647}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2650{
2651 struct stream_out *out = (struct stream_out *)stream;
2652 struct audio_device *adev = out->dev;
2653 struct str_parms *parms;
2654 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002655 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656
sangwoobc677242013-08-08 16:53:43 +09002657 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002658 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302660 if (!parms)
2661 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002662 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2663 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002665 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002666 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002668 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002669 * When HDMI cable is unplugged the music playback is paused and
2670 * the policy manager sends routing=0. But the audioflinger continues
2671 * to write data until standby time (3sec). As the HDMI core is
2672 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002673 * Avoid this by routing audio to speaker until standby.
2674 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002675 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2676 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302677 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002678 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2679 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002680 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302681 /*
2682 * When A2DP is disconnected the
2683 * music playback is paused and the policy manager sends routing=0
2684 * But the audioflingercontinues to write data until standby time
2685 * (3sec). As BT is turned off, the write gets blocked.
2686 * Avoid this by routing audio to speaker until standby.
2687 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002688 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302689 (val == AUDIO_DEVICE_NONE)) {
2690 val = AUDIO_DEVICE_OUT_SPEAKER;
2691 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302692 /* To avoid a2dp to sco overlapping / BT device improper state
2693 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302694 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302695 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2696 if (!audio_extn_a2dp_is_ready()) {
2697 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2698 //combo usecase just by pass a2dp
2699 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2700 val = AUDIO_DEVICE_OUT_SPEAKER;
2701 } else {
2702 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2703 /* update device to a2dp and don't route as BT returned error
2704 * However it is still possible a2dp routing called because
2705 * of current active device disconnection (like wired headset)
2706 */
2707 out->devices = val;
2708 pthread_mutex_unlock(&out->lock);
2709 pthread_mutex_unlock(&adev->lock);
2710 goto error;
2711 }
2712 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302713 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002714 /*
2715 * select_devices() call below switches all the usecases on the same
2716 * backend to the new device. Refer to check_usecases_codec_backend() in
2717 * the select_devices(). But how do we undo this?
2718 *
2719 * For example, music playback is active on headset (deep-buffer usecase)
2720 * and if we go to ringtones and select a ringtone, low-latency usecase
2721 * will be started on headset+speaker. As we can't enable headset+speaker
2722 * and headset devices at the same time, select_devices() switches the music
2723 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2724 * So when the ringtone playback is completed, how do we undo the same?
2725 *
2726 * We are relying on the out_set_parameters() call on deep-buffer output,
2727 * once the ringtone playback is ended.
2728 * NOTE: We should not check if the current devices are same as new devices.
2729 * Because select_devices() must be called to switch back the music
2730 * playback to headset.
2731 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002732 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002733 audio_devices_t new_dev = val;
2734 bool same_dev = out->devices == new_dev;
2735 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002736
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002737 if (output_drives_call(adev, out)) {
2738 if(!voice_is_in_call(adev)) {
2739 if (adev->mode == AUDIO_MODE_IN_CALL) {
2740 adev->current_call_output = out;
2741 ret = voice_start_call(adev);
2742 }
2743 } else {
2744 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002745 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002746 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002747 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002748
2749 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002750 if (!same_dev) {
2751 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302752 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2753 adev->perf_lock_opts,
2754 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002755 if (adev->adm_on_routing_change)
2756 adev->adm_on_routing_change(adev->adm_data,
2757 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002758 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002759 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302760 if (!same_dev)
2761 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002762 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002763 }
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002766 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002768
2769 if (out == adev->primary_output) {
2770 pthread_mutex_lock(&adev->lock);
2771 audio_extn_set_parameters(adev, parms);
2772 pthread_mutex_unlock(&adev->lock);
2773 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002774 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002775 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002776 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002777
2778 audio_extn_dts_create_state_notifier_node(out->usecase);
2779 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2780 popcount(out->channel_mask),
2781 out->playback_started);
2782
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002783 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002784 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002785
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302786 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2787 if (err >= 0) {
2788 strlcpy(out->profile, value, sizeof(out->profile));
2789 ALOGV("updating stream profile with value '%s'", out->profile);
2790 lock_output_stream(out);
2791 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2792 &adev->streams_output_cfg_list,
2793 out->devices, out->flags, out->format,
2794 out->sample_rate, out->bit_width,
2795 out->channel_mask, out->profile,
2796 &out->app_type_cfg);
2797 pthread_mutex_unlock(&out->lock);
2798 }
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302801error:
Eric Laurent994a6932013-07-17 11:51:42 -07002802 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 return ret;
2804}
2805
2806static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2807{
2808 struct stream_out *out = (struct stream_out *)stream;
2809 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002810 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 char value[256];
2812 struct str_parms *reply = str_parms_create();
2813 size_t i, j;
2814 int ret;
2815 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002816
2817 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002818 if (reply) {
2819 str_parms_destroy(reply);
2820 }
2821 if (query) {
2822 str_parms_destroy(query);
2823 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002824 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2825 return NULL;
2826 }
2827
Eric Laurent994a6932013-07-17 11:51:42 -07002828 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2830 if (ret >= 0) {
2831 value[0] = '\0';
2832 i = 0;
2833 while (out->supported_channel_masks[i] != 0) {
2834 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2835 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2836 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002837 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002839 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 first = false;
2841 break;
2842 }
2843 }
2844 i++;
2845 }
2846 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2847 str = str_parms_to_str(reply);
2848 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002849 voice_extn_out_get_parameters(out, query, reply);
2850 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002851 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002852 free(str);
2853 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002854 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002856
Alexy Joseph62142aa2015-11-16 15:10:34 -08002857
2858 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2859 if (ret >= 0) {
2860 value[0] = '\0';
2861 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2862 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302863 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002864 } else {
2865 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302866 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002867 }
2868 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002869 if (str)
2870 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002871 str = str_parms_to_str(reply);
2872 }
2873
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002874 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2875 if (ret >= 0) {
2876 value[0] = '\0';
2877 i = 0;
2878 first = true;
2879 while (out->supported_formats[i] != 0) {
2880 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2881 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2882 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002883 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002884 }
2885 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2886 first = false;
2887 break;
2888 }
2889 }
2890 i++;
2891 }
2892 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002893 if (str)
2894 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002895 str = str_parms_to_str(reply);
2896 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002897
2898 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2899 if (ret >= 0) {
2900 value[0] = '\0';
2901 i = 0;
2902 first = true;
2903 while (out->supported_sample_rates[i] != 0) {
2904 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2905 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2906 if (!first) {
2907 strlcat(value, "|", sizeof(value));
2908 }
2909 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2910 first = false;
2911 break;
2912 }
2913 }
2914 i++;
2915 }
2916 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2917 if (str)
2918 free(str);
2919 str = str_parms_to_str(reply);
2920 }
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 str_parms_destroy(query);
2923 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002924 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 return str;
2926}
2927
2928static uint32_t out_get_latency(const struct audio_stream_out *stream)
2929{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002930 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002932 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933
Alexy Josephaa54c872014-12-03 02:46:47 -08002934 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002935 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002936 } else if (out->realtime) {
2937 // since the buffer won't be filled up faster than realtime,
2938 // return a smaller number
2939 if (out->config.rate)
2940 period_ms = (out->af_period_multiplier * out->config.period_size *
2941 1000) / (out->config.rate);
2942 else
2943 period_ms = 0;
2944 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002945 } else {
2946 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002948 }
2949
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002950 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2951 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2952 latency += audio_extn_a2dp_get_encoder_latency();
2953
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302954 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002955 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956}
2957
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302958static float AmpToDb(float amplification)
2959{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302960 float db = DSD_VOLUME_MIN_DB;
2961 if (amplification > 0) {
2962 db = 20 * log10(amplification);
2963 if(db < DSD_VOLUME_MIN_DB)
2964 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302965 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302966 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302967}
2968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969static int out_set_volume(struct audio_stream_out *stream, float left,
2970 float right)
2971{
Eric Laurenta9024de2013-04-04 09:19:12 -07002972 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 int volume[2];
2974
Eric Laurenta9024de2013-04-04 09:19:12 -07002975 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2976 /* only take left channel into account: the API is for stereo anyway */
2977 out->muted = (left == 0.0f);
2978 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002979 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302980 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002981 /*
2982 * Set mute or umute on HDMI passthrough stream.
2983 * Only take left channel into account.
2984 * Mute is 0 and unmute 1
2985 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302986 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302987 } else if (out->format == AUDIO_FORMAT_DSD){
2988 char mixer_ctl_name[128] = "DSD Volume";
2989 struct audio_device *adev = out->dev;
2990 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2991
2992 if (!ctl) {
2993 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2994 __func__, mixer_ctl_name);
2995 return -EINVAL;
2996 }
2997 volume[0] = (int)(AmpToDb(left));
2998 volume[1] = (int)(AmpToDb(right));
2999 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3000 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003001 } else {
3002 char mixer_ctl_name[128];
3003 struct audio_device *adev = out->dev;
3004 struct mixer_ctl *ctl;
3005 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003006 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003008 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3009 "Compress Playback %d Volume", pcm_device_id);
3010 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3011 if (!ctl) {
3012 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3013 __func__, mixer_ctl_name);
3014 return -EINVAL;
3015 }
3016 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3017 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3018 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3019 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003021 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 return -ENOSYS;
3024}
3025
3026static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3027 size_t bytes)
3028{
3029 struct stream_out *out = (struct stream_out *)stream;
3030 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303031 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003032 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003034 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303035
Naresh Tanniru80659832014-06-04 18:17:56 +05303036 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003037
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05303038 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303039 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303040 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3041 pthread_mutex_unlock(&out->lock);
3042 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303043 } else {
3044 /* increase written size during SSR to avoid mismatch
3045 * with the written frames count in AF
3046 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003047 // bytes per frame
3048 size_t bpf = audio_bytes_per_sample(out->format) *
3049 audio_channel_count_from_out_mask(out->channel_mask);
3050 if (bpf != 0)
3051 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303052 ALOGD(" %s: sound card is not active/SSR state", __func__);
3053 ret= -EIO;
3054 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303055 }
3056 }
3057
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303058 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303059 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3060 if (audio_bytes_per_sample(out->format) != 0)
3061 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3062 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303063 goto exit;
3064 }
3065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003067 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003068 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003069 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3070 ret = voice_extn_compress_voip_start_output_stream(out);
3071 else
3072 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003073 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003076 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 goto exit;
3078 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003079
3080 if (last_known_cal_step != -1) {
3081 ALOGD("%s: retry previous failed cal level set", __func__);
3082 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085
Ashish Jain81eb2a82015-05-13 10:52:34 +05303086 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003087 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303088 adev->is_channel_status_set = true;
3089 }
3090
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003091 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003092 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003093 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003094 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003095 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3096 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303097 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3098 ALOGD("copl(%p):send next track params in gapless", out);
3099 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3100 out->send_next_track_params = false;
3101 out->is_compr_metadata_avail = false;
3102 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003103 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303104 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303105 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003106
Ashish Jain83a6cc22016-06-28 14:34:17 +05303107 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303108 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303109 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303110 pthread_mutex_unlock(&out->lock);
3111 return -EINVAL;
3112 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303113 audio_format_t dst_format = out->hal_op_format;
3114 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303115
3116 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3117 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3118
Ashish Jain83a6cc22016-06-28 14:34:17 +05303119 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303120 dst_format,
3121 buffer,
3122 src_format,
3123 frames);
3124
Ashish Jain83a6cc22016-06-28 14:34:17 +05303125 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303126 bytes_to_write);
3127
3128 /*Convert written bytes in audio flinger format*/
3129 if (ret > 0)
3130 ret = ((ret * format_to_bitwidth_table[out->format]) /
3131 format_to_bitwidth_table[dst_format]);
3132 }
3133 } else
3134 ret = compress_write(out->compr, buffer, bytes);
3135
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303136 if (ret < 0)
3137 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303138 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303139 /*msg to cb thread only if non blocking write is enabled*/
3140 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303141 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303143 } else if (-ENETRESET == ret) {
3144 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3146 pthread_mutex_unlock(&out->lock);
3147 out_standby(&out->stream.common);
3148 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149 }
Ashish Jain5106d362016-05-11 19:23:33 +05303150 if ( ret == (ssize_t)bytes && !out->non_blocking)
3151 out->written += bytes;
3152
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303153 /* Call compr start only when non-zero bytes of data is there to be rendered */
3154 if (!out->playback_started && ret > 0) {
3155 int status = compress_start(out->compr);
3156 if (status < 0) {
3157 ret = status;
3158 ALOGE("%s: compr start failed with err %d", __func__, errno);
3159 goto exit;
3160 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003161 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003162 out->playback_started = 1;
3163 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003164
3165 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3166 popcount(out->channel_mask),
3167 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003168 }
3169 pthread_mutex_unlock(&out->lock);
3170 return ret;
3171 } else {
3172 if (out->pcm) {
3173 if (out->muted)
3174 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003175
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303176 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003177
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003178 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003179
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003180 if (out->config.rate)
3181 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3182 out->config.rate;
3183
3184 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3185
3186 request_out_focus(out, ns);
3187
3188 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003189 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003190 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303191 out->convert_buffer != NULL) {
3192
3193 memcpy_by_audio_format(out->convert_buffer,
3194 out->hal_op_format,
3195 buffer,
3196 out->hal_ip_format,
3197 out->config.period_size * out->config.channels);
3198
3199 ret = pcm_write(out->pcm, out->convert_buffer,
3200 (out->config.period_size *
3201 out->config.channels *
3202 format_to_bitwidth_table[out->hal_op_format]));
3203 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003204 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303205 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003206
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003207 release_out_focus(out);
3208
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303209 if (ret < 0)
3210 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303211 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3212 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3213 else
3214 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 }
3217
3218exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303219 /* ToDo: There may be a corner case when SSR happens back to back during
3220 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303221 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303222 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303223 }
3224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 pthread_mutex_unlock(&out->lock);
3226
3227 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003228 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003229 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303230 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303231 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303232 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303233 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303234 out->standby = true;
3235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303237 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3238 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3239 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 }
3241 return bytes;
3242}
3243
3244static int out_get_render_position(const struct audio_stream_out *stream,
3245 uint32_t *dsp_frames)
3246{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303248 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003249
3250 if (dsp_frames == NULL)
3251 return -EINVAL;
3252
3253 *dsp_frames = 0;
3254 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003255 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303256
3257 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3258 * this operation and adev_close_output_stream(where out gets reset).
3259 */
3260 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3261 *dsp_frames = get_actual_pcm_frames_rendered(out);
3262 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3263 return 0;
3264 }
3265
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003266 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303267 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303268 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003269 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303270 if (ret < 0)
3271 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303273 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 }
3275 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303276 if (-ENETRESET == ret) {
3277 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3278 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3279 return -EINVAL;
3280 } else if(ret < 0) {
3281 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3282 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303283 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3284 /*
3285 * Handle corner case where compress session is closed during SSR
3286 * and timestamp is queried
3287 */
3288 ALOGE(" ERROR: sound card not active, return error");
3289 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303290 } else {
3291 return 0;
3292 }
Zhou Song32a556e2015-05-05 10:46:56 +08003293 } else if (audio_is_linear_pcm(out->format)) {
3294 *dsp_frames = out->written;
3295 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 } else
3297 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298}
3299
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003300static int out_add_audio_effect(const struct audio_stream *stream __unused,
3301 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302{
3303 return 0;
3304}
3305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003306static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3307 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308{
3309 return 0;
3310}
3311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003312static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3313 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314{
3315 return -EINVAL;
3316}
3317
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003318static int out_get_presentation_position(const struct audio_stream_out *stream,
3319 uint64_t *frames, struct timespec *timestamp)
3320{
3321 struct stream_out *out = (struct stream_out *)stream;
3322 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003323 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003324
Ashish Jain5106d362016-05-11 19:23:33 +05303325 /* below piece of code is not guarded against any lock because audioFliner serializes
3326 * this operation and adev_close_output_stream( where out gets reset).
3327 */
3328 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3329 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3330 *frames = get_actual_pcm_frames_rendered(out);
3331 /* this is the best we can do */
3332 clock_gettime(CLOCK_MONOTONIC, timestamp);
3333 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3334 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3335 return 0;
3336 }
3337
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003338 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003339
Ashish Jain5106d362016-05-11 19:23:33 +05303340 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3341 ret = compress_get_tstamp(out->compr, &dsp_frames,
3342 &out->sample_rate);
3343 ALOGVV("%s rendered frames %ld sample_rate %d",
3344 __func__, dsp_frames, out->sample_rate);
3345 *frames = dsp_frames;
3346 if (ret < 0)
3347 ret = -errno;
3348 if (-ENETRESET == ret) {
3349 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3350 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3351 ret = -EINVAL;
3352 } else
3353 ret = 0;
3354 /* this is the best we can do */
3355 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003356 } else {
3357 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003358 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003359 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3360 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003361 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003362 // This adjustment accounts for buffering after app processor.
3363 // It is based on estimated DSP latency per use case, rather than exact.
3364 signed_frames -=
3365 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3366
Eric Laurent949a0892013-09-20 09:20:13 -07003367 // It would be unusual for this value to be negative, but check just in case ...
3368 if (signed_frames >= 0) {
3369 *frames = signed_frames;
3370 ret = 0;
3371 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003372 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303373 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3374 *frames = out->written;
3375 clock_gettime(CLOCK_MONOTONIC, timestamp);
3376 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003377 }
3378 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003379 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003380 return ret;
3381}
3382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383static int out_set_callback(struct audio_stream_out *stream,
3384 stream_callback_t callback, void *cookie)
3385{
3386 struct stream_out *out = (struct stream_out *)stream;
3387
3388 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003389 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003390 out->offload_callback = callback;
3391 out->offload_cookie = cookie;
3392 pthread_mutex_unlock(&out->lock);
3393 return 0;
3394}
3395
3396static int out_pause(struct audio_stream_out* stream)
3397{
3398 struct stream_out *out = (struct stream_out *)stream;
3399 int status = -ENOSYS;
3400 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003401 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003402 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003403 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003404 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303405 struct audio_device *adev = out->dev;
3406 int snd_scard_state = get_snd_card_state(adev);
3407
3408 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3409 status = compress_pause(out->compr);
3410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003411 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003412
Mingming Yin21854652016-04-13 11:54:02 -07003413 if (audio_extn_passthru_is_active()) {
3414 ALOGV("offload use case, pause passthru");
3415 audio_extn_passthru_on_pause(out);
3416 }
3417
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303418 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003419 audio_extn_dts_notify_playback_state(out->usecase, 0,
3420 out->sample_rate, popcount(out->channel_mask),
3421 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003422 }
3423 pthread_mutex_unlock(&out->lock);
3424 }
3425 return status;
3426}
3427
3428static int out_resume(struct audio_stream_out* stream)
3429{
3430 struct stream_out *out = (struct stream_out *)stream;
3431 int status = -ENOSYS;
3432 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003433 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003434 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003436 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003437 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303438 struct audio_device *adev = out->dev;
3439 int snd_scard_state = get_snd_card_state(adev);
3440
Mingming Yin21854652016-04-13 11:54:02 -07003441 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3442 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3443 pthread_mutex_lock(&out->dev->lock);
3444 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003445 pthread_mutex_unlock(&out->dev->lock);
3446 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303447 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003448 }
3449 if (!status) {
3450 out->offload_state = OFFLOAD_STATE_PLAYING;
3451 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303452 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003453 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3454 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003455 }
3456 pthread_mutex_unlock(&out->lock);
3457 }
3458 return status;
3459}
3460
3461static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3462{
3463 struct stream_out *out = (struct stream_out *)stream;
3464 int status = -ENOSYS;
3465 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003466 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003467 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3469 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3470 else
3471 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3472 pthread_mutex_unlock(&out->lock);
3473 }
3474 return status;
3475}
3476
3477static int out_flush(struct audio_stream_out* stream)
3478{
3479 struct stream_out *out = (struct stream_out *)stream;
3480 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003481 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003482 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003483 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003484 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3485 stop_compressed_output_l(out);
3486 out->written = 0;
3487 } else {
3488 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3489 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003491 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492 return 0;
3493 }
3494 return -ENOSYS;
3495}
3496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497/** audio_stream_in implementation **/
3498static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3499{
3500 struct stream_in *in = (struct stream_in *)stream;
3501
3502 return in->config.rate;
3503}
3504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003505static int in_set_sample_rate(struct audio_stream *stream __unused,
3506 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507{
3508 return -ENOSYS;
3509}
3510
3511static size_t in_get_buffer_size(const struct audio_stream *stream)
3512{
3513 struct stream_in *in = (struct stream_in *)stream;
3514
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003515 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3516 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003517 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3518 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303519 else if(audio_extn_cin_attached_usecase(in->usecase))
3520 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003521
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003522 return in->config.period_size * in->af_period_multiplier *
3523 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524}
3525
3526static uint32_t in_get_channels(const struct audio_stream *stream)
3527{
3528 struct stream_in *in = (struct stream_in *)stream;
3529
3530 return in->channel_mask;
3531}
3532
3533static audio_format_t in_get_format(const struct audio_stream *stream)
3534{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003535 struct stream_in *in = (struct stream_in *)stream;
3536
3537 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538}
3539
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003540static int in_set_format(struct audio_stream *stream __unused,
3541 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542{
3543 return -ENOSYS;
3544}
3545
3546static int in_standby(struct audio_stream *stream)
3547{
3548 struct stream_in *in = (struct stream_in *)stream;
3549 struct audio_device *adev = in->dev;
3550 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303551 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3552 stream, in->usecase, use_case_table[in->usecase]);
3553
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003554 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003555 if (!in->standby && in->is_st_session) {
3556 ALOGD("%s: sound trigger pcm stop lab", __func__);
3557 audio_extn_sound_trigger_stop_lab(in);
3558 in->standby = 1;
3559 }
3560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003562 if (adev->adm_deregister_stream)
3563 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3564
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003565 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003567 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3568 voice_extn_compress_voip_close_input_stream(stream);
3569 ALOGD("VOIP input entered standby");
3570 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303571 if (audio_extn_cin_attached_usecase(in->usecase))
3572 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003573 if (in->pcm) {
3574 pcm_close(in->pcm);
3575 in->pcm = NULL;
3576 }
3577 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003578 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003579 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 }
3581 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003582 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583 return status;
3584}
3585
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003586static int in_dump(const struct audio_stream *stream __unused,
3587 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588{
3589 return 0;
3590}
3591
3592static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3593{
3594 struct stream_in *in = (struct stream_in *)stream;
3595 struct audio_device *adev = in->dev;
3596 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003598 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303600 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 parms = str_parms_create_str(kvpairs);
3602
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303603 if (!parms)
3604 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003605 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003606 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003607
3608 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3609 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 val = atoi(value);
3611 /* no audio source uses val == 0 */
3612 if ((in->source != val) && (val != 0)) {
3613 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003614 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3615 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3616 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003617 (in->config.rate == 8000 || in->config.rate == 16000 ||
3618 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003619 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003620 err = voice_extn_compress_voip_open_input_stream(in);
3621 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003622 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003623 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003624 }
3625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 }
3627 }
3628
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003629 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3630 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003632 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 in->device = val;
3634 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003635 if (!in->standby && !in->is_st_session) {
3636 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003637 if (adev->adm_on_routing_change)
3638 adev->adm_on_routing_change(adev->adm_data,
3639 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003640 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 }
3643 }
3644
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303645 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3646 if (err >= 0) {
3647 strlcpy(in->profile, value, sizeof(in->profile));
3648 ALOGV("updating stream profile with value '%s'", in->profile);
3649 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3650 &adev->streams_input_cfg_list,
3651 in->device, in->flags, in->format,
3652 in->sample_rate, in->bit_width,
3653 in->profile, &in->app_type_cfg);
3654 }
3655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003657 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658
3659 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303660error:
Eric Laurent994a6932013-07-17 11:51:42 -07003661 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 return ret;
3663}
3664
3665static char* in_get_parameters(const struct audio_stream *stream,
3666 const char *keys)
3667{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003668 struct stream_in *in = (struct stream_in *)stream;
3669 struct str_parms *query = str_parms_create_str(keys);
3670 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003671 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003672
3673 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003674 if (reply) {
3675 str_parms_destroy(reply);
3676 }
3677 if (query) {
3678 str_parms_destroy(query);
3679 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003680 ALOGE("in_get_parameters: failed to create query or reply");
3681 return NULL;
3682 }
3683
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003684 ALOGV("%s: enter: keys - %s", __func__, keys);
3685
3686 voice_extn_in_get_parameters(in, query, reply);
3687
3688 str = str_parms_to_str(reply);
3689 str_parms_destroy(query);
3690 str_parms_destroy(reply);
3691
3692 ALOGV("%s: exit: returns - %s", __func__, str);
3693 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694}
3695
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003696static int in_set_gain(struct audio_stream_in *stream __unused,
3697 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698{
3699 return 0;
3700}
3701
3702static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3703 size_t bytes)
3704{
3705 struct stream_in *in = (struct stream_in *)stream;
3706 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303707 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303708 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303709 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003711 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303712
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003713 if (in->is_st_session) {
3714 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3715 /* Read from sound trigger HAL */
3716 audio_extn_sound_trigger_read(in, buffer, bytes);
3717 pthread_mutex_unlock(&in->lock);
3718 return bytes;
3719 }
3720
Ashish Jainbbce4322016-02-16 13:25:27 +05303721 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003722 ALOGD(" %s: sound card is not active/SSR state", __func__);
3723 ret= -EIO;;
3724 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303725 }
3726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003728 pthread_mutex_lock(&adev->lock);
3729 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3730 ret = voice_extn_compress_voip_start_input_stream(in);
3731 else
3732 ret = start_input_stream(in);
3733 pthread_mutex_unlock(&adev->lock);
3734 if (ret != 0) {
3735 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 }
3737 in->standby = 0;
3738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003740 // what's the duration requested by the client?
3741 long ns = 0;
3742
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303743 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003744 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3745 in->config.rate;
3746
3747 request_in_focus(in, ns);
3748 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003749
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303750 if (audio_extn_cin_attached_usecase(in->usecase)) {
3751 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3752 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303753 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003754 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303755 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003756 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003757 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003758 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303759 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003760 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303761 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3762 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3763 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3764 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303765 ret = -EINVAL;
3766 goto exit;
3767 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303768 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303769 ret = -errno;
3770 }
3771 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303772 /* bytes read is always set to bytes for non compress usecases */
3773 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 }
3775
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003776 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 /*
3779 * Instead of writing zeroes here, we could trust the hardware
3780 * to always provide zeroes when muted.
3781 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303782 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3783 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 memset(buffer, 0, bytes);
3785
3786exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303787 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303788 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003789 if (-ENETRESET == ret)
3790 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 pthread_mutex_unlock(&in->lock);
3793
3794 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303795 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303796 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303797 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303798 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303799 in->standby = true;
3800 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303801 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3802 bytes_read = bytes;
3803 memset(buffer, 0, bytes);
3804 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003806 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303807 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303808 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303810 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811}
3812
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003813static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814{
3815 return 0;
3816}
3817
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003818static int add_remove_audio_effect(const struct audio_stream *stream,
3819 effect_handle_t effect,
3820 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003822 struct stream_in *in = (struct stream_in *)stream;
3823 int status = 0;
3824 effect_descriptor_t desc;
3825
3826 status = (*effect)->get_descriptor(effect, &desc);
3827 if (status != 0)
3828 return status;
3829
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003830 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003831 pthread_mutex_lock(&in->dev->lock);
3832 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3833 in->enable_aec != enable &&
3834 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3835 in->enable_aec = enable;
3836 if (!in->standby)
3837 select_devices(in->dev, in->usecase);
3838 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003839 if (in->enable_ns != enable &&
3840 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3841 in->enable_ns = enable;
3842 if (!in->standby)
3843 select_devices(in->dev, in->usecase);
3844 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003845 pthread_mutex_unlock(&in->dev->lock);
3846 pthread_mutex_unlock(&in->lock);
3847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 return 0;
3849}
3850
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003851static int in_add_audio_effect(const struct audio_stream *stream,
3852 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853{
Eric Laurent994a6932013-07-17 11:51:42 -07003854 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003855 return add_remove_audio_effect(stream, effect, true);
3856}
3857
3858static int in_remove_audio_effect(const struct audio_stream *stream,
3859 effect_handle_t effect)
3860{
Eric Laurent994a6932013-07-17 11:51:42 -07003861 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003862 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863}
3864
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303865int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 audio_io_handle_t handle,
3867 audio_devices_t devices,
3868 audio_output_flags_t flags,
3869 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003870 struct audio_stream_out **stream_out,
3871 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872{
3873 struct audio_device *adev = (struct audio_device *)dev;
3874 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303875 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003876 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303879
3880 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3881 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003882 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303883 return -EINVAL;
3884 }
3885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3887
Mingming Yin3a941d42016-02-17 18:08:05 -08003888 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3889 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303890 devices, flags, &out->stream);
3891
3892
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003893 if (!out) {
3894 return -ENOMEM;
3895 }
3896
Haynes Mathew George204045b2015-02-25 20:32:03 -08003897 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003898 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003899 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 if (devices == AUDIO_DEVICE_NONE)
3902 devices = AUDIO_DEVICE_OUT_SPEAKER;
3903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 out->flags = flags;
3905 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003906 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003907 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003908 out->sample_rate = config->sample_rate;
3909 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3910 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003911 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003912 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003913 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303914 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915
Mingming Yin3a941d42016-02-17 18:08:05 -08003916 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3917 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3918 pthread_mutex_lock(&adev->lock);
3919 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3920 ret = read_hdmi_sink_caps(out);
3921 pthread_mutex_unlock(&adev->lock);
3922 if (ret != 0) {
3923 if (ret == -ENOSYS) {
3924 /* ignore and go with default */
3925 ret = 0;
3926 } else {
3927 ALOGE("error reading hdmi sink caps");
3928 goto error_open;
3929 }
3930 }
3931 }
3932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003934 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303935 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3936 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003937 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3938 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3939
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003940 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003941 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3942 /*
3943 * Do not handle stereo output in Multi-channel cases
3944 * Stereo case is handled in normal playback path
3945 */
3946 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3947 ret = AUDIO_CHANNEL_OUT_STEREO;
3948 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003949
3950 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3951 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003952 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003953 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003954 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003955
3956 if (config->sample_rate == 0)
3957 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3958 if (config->channel_mask == 0)
3959 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003960 if (config->format == 0)
3961 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003962
3963 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003965 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3967 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003969 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003971 } 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 -08003972 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003973 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003974 ret = voice_extn_compress_voip_open_output_stream(out);
3975 if (ret != 0) {
3976 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3977 __func__, ret);
3978 goto error_open;
3979 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003980 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3981 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3984 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3985 ALOGE("%s: Unsupported Offload information", __func__);
3986 ret = -EINVAL;
3987 goto error_open;
3988 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003989
Mingming Yin3a941d42016-02-17 18:08:05 -08003990 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003991 if(config->offload_info.format == 0)
3992 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003993 if (config->offload_info.sample_rate == 0)
3994 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003995 }
3996
Mingming Yin90310102013-11-13 16:57:00 -08003997 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303998 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003999 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004000 ret = -EINVAL;
4001 goto error_open;
4002 }
4003
4004 out->compr_config.codec = (struct snd_codec *)
4005 calloc(1, sizeof(struct snd_codec));
4006
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004007 if (!out->compr_config.codec) {
4008 ret = -ENOMEM;
4009 goto error_open;
4010 }
4011
vivek mehta0ea887a2015-08-26 14:01:20 -07004012 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304013 out->stream.pause = out_pause;
4014 out->stream.flush = out_flush;
4015 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07004016 out->usecase = get_offload_usecase(adev, true);
4017 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004018 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07004019 out->stream.set_callback = out_set_callback;
4020 out->stream.pause = out_pause;
4021 out->stream.resume = out_resume;
4022 out->stream.drain = out_drain;
4023 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07004024 out->usecase = get_offload_usecase(adev, false);
4025 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004026 }
vivek mehta446c3962015-09-14 10:57:35 -07004027
4028 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004029 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4030 config->format == 0 && config->sample_rate == 0 &&
4031 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004032 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004033 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4034 } else {
4035 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4036 ret = -EEXIST;
4037 goto error_open;
4038 }
vivek mehta446c3962015-09-14 10:57:35 -07004039 }
4040
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004041 if (config->offload_info.channel_mask)
4042 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004043 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004045 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004046 } else {
4047 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
4048 ret = -EINVAL;
4049 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004050 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004051
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004052 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004053 out->sample_rate = config->offload_info.sample_rate;
4054
Mingming Yin3ee55c62014-08-04 14:23:35 -07004055 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004056
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304057 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4058 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4059 audio_extn_dolby_send_ddp_endp_params(adev);
4060 audio_extn_dolby_set_dmid(adev);
4061 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004062
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004063 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004064 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065 out->compr_config.codec->bit_rate =
4066 config->offload_info.bit_rate;
4067 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304068 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004069 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304070 /* Update bit width only for non passthrough usecases.
4071 * For passthrough usecases, the output will always be opened @16 bit
4072 */
4073 if (!audio_extn_passthru_is_passthrough_stream(out))
4074 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004075 /*TODO: Do we need to change it for passthrough */
4076 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077
Manish Dewangana6fc5442015-08-24 20:30:31 +05304078 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4079 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304080 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304081 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304082 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4083 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304084
4085 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4086 AUDIO_FORMAT_PCM) {
4087
4088 /*Based on platform support, configure appropriate alsa format for corresponding
4089 *hal input format.
4090 */
4091 out->compr_config.codec->format = hal_format_to_alsa(
4092 config->offload_info.format);
4093
Ashish Jain83a6cc22016-06-28 14:34:17 +05304094 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304095 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304096 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304097
4098 /*for direct PCM playback populate bit_width based on selected alsa format as
4099 *hal input format and alsa format might differ based on platform support.
4100 */
4101 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304102 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304103
4104 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4105
4106 /* Check if alsa session is configured with the same format as HAL input format,
4107 * if not then derive correct fragment size needed to accomodate the
4108 * conversion of HAL input format to alsa format.
4109 */
4110 audio_extn_utils_update_direct_pcm_fragment_size(out);
4111
4112 /*if hal input and output fragment size is different this indicates HAL input format is
4113 *not same as the alsa format
4114 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304115 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304116 /*Allocate a buffer to convert input data to the alsa configured format.
4117 *size of convert buffer is equal to the size required to hold one fragment size
4118 *worth of pcm data, this is because flinger does not write more than fragment_size
4119 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304120 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4121 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304122 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4123 ret = -ENOMEM;
4124 goto error_open;
4125 }
4126 }
4127 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4128 out->compr_config.fragment_size =
4129 audio_extn_passthru_get_buffer_size(&config->offload_info);
4130 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4131 } else {
4132 out->compr_config.fragment_size =
4133 platform_get_compress_offload_buffer_size(&config->offload_info);
4134 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4135 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004136
Amit Shekhar6f461b12014-08-01 14:52:58 -07004137 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304138 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004139
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304140 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4141 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4142 }
4143
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004144 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4145 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004146
Alexy Josephaa54c872014-12-03 02:46:47 -08004147
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004148 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304149 out->send_next_track_params = false;
4150 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004151 out->offload_state = OFFLOAD_STATE_IDLE;
4152 out->playback_started = 0;
4153
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004154 audio_extn_dts_create_state_notifier_node(out->usecase);
4155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004156 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4157 __func__, config->offload_info.version,
4158 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304159
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304160 /* Check if DSD audio format is supported in codec
4161 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304162 */
4163
4164 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304165 (!platform_check_codec_dsd_support(adev->platform) ||
4166 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304167 ret = -EINVAL;
4168 goto error_open;
4169 }
4170
Ashish Jain5106d362016-05-11 19:23:33 +05304171 /* Disable gapless if any of the following is true
4172 * passthrough playback
4173 * AV playback
4174 * Direct PCM playback
4175 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304176 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304177 (config->format == AUDIO_FORMAT_DSD) ||
4178 config->offload_info.has_video ||
4179 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304180 check_and_set_gapless_mode(adev, false);
4181 } else
4182 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004183
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304184 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004185 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4186 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304187 if (config->format == AUDIO_FORMAT_DSD) {
4188 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4189 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4190 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004191
4192 create_offload_callback_thread(out);
4193
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004194 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304195 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004196 if (ret != 0) {
4197 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4198 __func__, ret);
4199 goto error_open;
4200 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004201 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4202 if (config->sample_rate == 0)
4203 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4204 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4205 config->sample_rate != 8000) {
4206 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4207 ret = -EINVAL;
4208 goto error_open;
4209 }
4210 out->sample_rate = config->sample_rate;
4211 out->config.rate = config->sample_rate;
4212 if (config->format == AUDIO_FORMAT_DEFAULT)
4213 config->format = AUDIO_FORMAT_PCM_16_BIT;
4214 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4215 config->format = AUDIO_FORMAT_PCM_16_BIT;
4216 ret = -EINVAL;
4217 goto error_open;
4218 }
4219 out->format = config->format;
4220 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4221 out->config = pcm_config_afe_proxy_playback;
4222 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004223 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304224 unsigned int channels = 0;
4225 /*Update config params to default if not set by the caller*/
4226 if (config->sample_rate == 0)
4227 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4228 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4229 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4230 if (config->format == AUDIO_FORMAT_DEFAULT)
4231 config->format = AUDIO_FORMAT_PCM_16_BIT;
4232
4233 channels = audio_channel_count_from_out_mask(out->channel_mask);
4234
Ashish Jain83a6cc22016-06-28 14:34:17 +05304235 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4236 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004237 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4238 out->flags);
4239 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304240 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4241 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4242 out->config = pcm_config_low_latency;
4243 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4244 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4245 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304246 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4247 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4248 if (out->config.period_size <= 0) {
4249 ALOGE("Invalid configuration period size is not valid");
4250 ret = -EINVAL;
4251 goto error_open;
4252 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304253 } else {
4254 /* primary path is the default path selected if no other outputs are available/suitable */
4255 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4256 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4257 }
4258 out->hal_ip_format = format = out->format;
4259 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4260 out->hal_op_format = pcm_format_to_hal(out->config.format);
4261 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4262 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004263 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304264 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304265 if (out->hal_ip_format != out->hal_op_format) {
4266 uint32_t buffer_size = out->config.period_size *
4267 format_to_bitwidth_table[out->hal_op_format] *
4268 out->config.channels;
4269 out->convert_buffer = calloc(1, buffer_size);
4270 if (out->convert_buffer == NULL){
4271 ALOGE("Allocation failed for convert buffer for size %d",
4272 out->compr_config.fragment_size);
4273 ret = -ENOMEM;
4274 goto error_open;
4275 }
4276 ALOGD("Convert buffer allocated of size %d", buffer_size);
4277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278 }
4279
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004280 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4281 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304282
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004283 /* TODO remove this hardcoding and check why width is zero*/
4284 if (out->bit_width == 0)
4285 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304286 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004287 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304288 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304289 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304290 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004291 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4292 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4293 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004294 if(adev->primary_output == NULL)
4295 adev->primary_output = out;
4296 else {
4297 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004298 ret = -EEXIST;
4299 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004300 }
4301 }
4302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 /* Check if this usecase is already existing */
4304 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004305 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4306 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004309 ret = -EEXIST;
4310 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 pthread_mutex_unlock(&adev->lock);
4314
4315 out->stream.common.get_sample_rate = out_get_sample_rate;
4316 out->stream.common.set_sample_rate = out_set_sample_rate;
4317 out->stream.common.get_buffer_size = out_get_buffer_size;
4318 out->stream.common.get_channels = out_get_channels;
4319 out->stream.common.get_format = out_get_format;
4320 out->stream.common.set_format = out_set_format;
4321 out->stream.common.standby = out_standby;
4322 out->stream.common.dump = out_dump;
4323 out->stream.common.set_parameters = out_set_parameters;
4324 out->stream.common.get_parameters = out_get_parameters;
4325 out->stream.common.add_audio_effect = out_add_audio_effect;
4326 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4327 out->stream.get_latency = out_get_latency;
4328 out->stream.set_volume = out_set_volume;
4329 out->stream.write = out_write;
4330 out->stream.get_render_position = out_get_render_position;
4331 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004332 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004334 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004336 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004337 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338
4339 config->format = out->stream.common.get_format(&out->stream.common);
4340 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4341 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4342
4343 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304344 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004345 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004346
4347 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4348 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4349 popcount(out->channel_mask), out->playback_started);
4350
Eric Laurent994a6932013-07-17 11:51:42 -07004351 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004353
4354error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304355 if (out->convert_buffer)
4356 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004357 free(out);
4358 *stream_out = NULL;
4359 ALOGD("%s: exit: ret %d", __func__, ret);
4360 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361}
4362
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304363void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364 struct audio_stream_out *stream)
4365{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004366 struct stream_out *out = (struct stream_out *)stream;
4367 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004368 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004369
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304370 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4371
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004372 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304373 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004374 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304375 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004376 if(ret != 0)
4377 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4378 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004379 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004380 out_standby(&stream->common);
4381
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004382 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004383 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004384 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004385 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004386 if (out->compr_config.codec != NULL)
4387 free(out->compr_config.codec);
4388 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004389
Ashish Jain83a6cc22016-06-28 14:34:17 +05304390 if (out->convert_buffer != NULL) {
4391 free(out->convert_buffer);
4392 out->convert_buffer = NULL;
4393 }
4394
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004395 if (adev->voice_tx_output == out)
4396 adev->voice_tx_output = NULL;
4397
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304398 if (adev->primary_output == out)
4399 adev->primary_output = NULL;
4400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004401 pthread_cond_destroy(&out->cond);
4402 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004404 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405}
4406
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004407static void close_compress_sessions(struct audio_device *adev)
4408{
Mingming Yin7b762e72015-03-04 13:47:32 -08004409 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304410 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004411 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004412 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304413
4414 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004415 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304416 if (is_offload_usecase(usecase->id)) {
4417 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004418 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4419 out = usecase->stream.out;
4420 pthread_mutex_unlock(&adev->lock);
4421 out_standby(&out->stream.common);
4422 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004423 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004424 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304425 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004426 }
4427 pthread_mutex_unlock(&adev->lock);
4428}
4429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4431{
4432 struct audio_device *adev = (struct audio_device *)dev;
4433 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004435 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004436 int ret;
4437 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004439 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304442 if (!parms)
4443 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004444 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4445 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304446 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304447 if (strstr(snd_card_status, "OFFLINE")) {
4448 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304449 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004450 //close compress sessions on OFFLINE status
4451 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304452 } else if (strstr(snd_card_status, "ONLINE")) {
4453 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304454 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004455 //send dts hpx license if enabled
4456 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304457 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304458 }
4459
4460 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004461 status = voice_set_parameters(adev, parms);
4462 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004463 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004465 status = platform_set_parameters(adev->platform, parms);
4466 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004467 goto done;
4468
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004469 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4470 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004471 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4473 adev->bluetooth_nrec = true;
4474 else
4475 adev->bluetooth_nrec = false;
4476 }
4477
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004478 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4479 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4481 adev->screen_off = false;
4482 else
4483 adev->screen_off = true;
4484 }
4485
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004486 ret = str_parms_get_int(parms, "rotation", &val);
4487 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004488 bool reverse_speakers = false;
4489 switch(val) {
4490 // FIXME: note that the code below assumes that the speakers are in the correct placement
4491 // relative to the user when the device is rotated 90deg from its default rotation. This
4492 // assumption is device-specific, not platform-specific like this code.
4493 case 270:
4494 reverse_speakers = true;
4495 break;
4496 case 0:
4497 case 90:
4498 case 180:
4499 break;
4500 default:
4501 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004502 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004503 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004504 if (status == 0) {
4505 if (adev->speaker_lr_swap != reverse_speakers) {
4506 adev->speaker_lr_swap = reverse_speakers;
4507 // only update the selected device if there is active pcm playback
4508 struct audio_usecase *usecase;
4509 struct listnode *node;
4510 list_for_each(node, &adev->usecase_list) {
4511 usecase = node_to_item(node, struct audio_usecase, list);
4512 if (usecase->type == PCM_PLAYBACK) {
4513 select_devices(adev, usecase->id);
4514 break;
4515 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004516 }
4517 }
4518 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004519 }
4520
Mingming Yin514a8bc2014-07-29 15:22:21 -07004521 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4522 if (ret >= 0) {
4523 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4524 adev->bt_wb_speech_enabled = true;
4525 else
4526 adev->bt_wb_speech_enabled = false;
4527 }
4528
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004529 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4530 if (ret >= 0) {
4531 val = atoi(value);
4532 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004533 ALOGV("cache new ext disp type and edid");
4534 ret = platform_get_ext_disp_type(adev->platform);
4535 if (ret < 0) {
4536 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004537 status = ret;
4538 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004539 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004540 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004541 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004542 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004543 /*
4544 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4545 * Per AudioPolicyManager, USB device is higher priority than WFD.
4546 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4547 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4548 * starting voice call on USB
4549 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004550 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4551 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004552 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4553 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004554 }
vivek mehta344576a2016-04-12 18:56:03 -07004555 ALOGV("detected USB connect .. disable proxy");
4556 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004557 }
4558 }
4559
4560 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4561 if (ret >= 0) {
4562 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004563 /*
4564 * The HDMI / Displayport disconnect handling has been moved to
4565 * audio extension to ensure that its parameters are not
4566 * invalidated prior to updating sysfs of the disconnect event
4567 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4568 */
4569 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004570 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004571 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4572 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304573 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4574 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004575 }
vivek mehta344576a2016-04-12 18:56:03 -07004576 ALOGV("detected USB disconnect .. enable proxy");
4577 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004578 }
4579 }
4580
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304581 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4582 if (ret >= 0) {
4583 struct audio_usecase *usecase;
4584 struct listnode *node;
4585 list_for_each(node, &adev->usecase_list) {
4586 usecase = node_to_item(node, struct audio_usecase, list);
4587 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004588 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304589 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304590 lock_output_stream(usecase->stream.out);
4591 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304592 //force device switch to re configure encoder
4593 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304594 audio_extn_a2dp_set_handoff_mode(false);
4595 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304596 break;
4597 }
4598 }
4599 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004600
4601 //handle vr audio setparam
4602 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4603 value, sizeof(value));
4604 if (ret >= 0) {
4605 ALOGI("Setting vr mode to be %s", value);
4606 if (!strncmp(value, "true", 4)) {
4607 adev->vr_audio_mode_enabled = true;
4608 ALOGI("Setting vr mode to true");
4609 } else if (!strncmp(value, "false", 5)) {
4610 adev->vr_audio_mode_enabled = false;
4611 ALOGI("Setting vr mode to false");
4612 } else {
4613 ALOGI("wrong vr mode set");
4614 }
4615 }
4616
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304617 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004618done:
4619 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004620 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304621error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004622 ALOGV("%s: exit with code(%d)", __func__, status);
4623 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624}
4625
4626static char* adev_get_parameters(const struct audio_hw_device *dev,
4627 const char *keys)
4628{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004629 struct audio_device *adev = (struct audio_device *)dev;
4630 struct str_parms *reply = str_parms_create();
4631 struct str_parms *query = str_parms_create_str(keys);
4632 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304633 char value[256] = {0};
4634 int ret = 0;
4635
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004636 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004637 if (reply) {
4638 str_parms_destroy(reply);
4639 }
4640 if (query) {
4641 str_parms_destroy(query);
4642 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004643 ALOGE("adev_get_parameters: failed to create query or reply");
4644 return NULL;
4645 }
4646
Naresh Tannirud7205b62014-06-20 02:54:48 +05304647 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4648 sizeof(value));
4649 if (ret >=0) {
4650 int val = 1;
4651 pthread_mutex_lock(&adev->snd_card_status.lock);
4652 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4653 val = 0;
4654 pthread_mutex_unlock(&adev->snd_card_status.lock);
4655 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4656 goto exit;
4657 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004658 //handle vr audio getparam
4659
4660 ret = str_parms_get_str(query,
4661 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4662 value, sizeof(value));
4663
4664 if (ret >= 0) {
4665 bool vr_audio_enabled = false;
4666 pthread_mutex_lock(&adev->lock);
4667 vr_audio_enabled = adev->vr_audio_mode_enabled;
4668 pthread_mutex_unlock(&adev->lock);
4669
4670 ALOGI("getting vr mode to %d", vr_audio_enabled);
4671
4672 if (vr_audio_enabled) {
4673 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4674 "true");
4675 goto exit;
4676 } else {
4677 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4678 "false");
4679 goto exit;
4680 }
4681 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004682
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004683 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004684 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004685 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004686 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304687 pthread_mutex_unlock(&adev->lock);
4688
Naresh Tannirud7205b62014-06-20 02:54:48 +05304689exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004690 str = str_parms_to_str(reply);
4691 str_parms_destroy(query);
4692 str_parms_destroy(reply);
4693
4694 ALOGV("%s: exit: returns - %s", __func__, str);
4695 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696}
4697
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004698static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699{
4700 return 0;
4701}
4702
4703static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4704{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004705 int ret;
4706 struct audio_device *adev = (struct audio_device *)dev;
4707 pthread_mutex_lock(&adev->lock);
4708 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004709 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004710 pthread_mutex_unlock(&adev->lock);
4711 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712}
4713
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004714static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4715 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716{
4717 return -ENOSYS;
4718}
4719
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004720static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4721 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722{
4723 return -ENOSYS;
4724}
4725
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004726static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4727 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728{
4729 return -ENOSYS;
4730}
4731
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004732static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4733 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004734{
4735 return -ENOSYS;
4736}
4737
4738static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4739{
4740 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 pthread_mutex_lock(&adev->lock);
4743 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004744 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004745 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004746 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004747 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004748 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004749 adev->current_call_output = NULL;
4750 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004751 }
4752 pthread_mutex_unlock(&adev->lock);
4753 return 0;
4754}
4755
4756static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4757{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004758 int ret;
4759
4760 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004761 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004762 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4763 pthread_mutex_unlock(&adev->lock);
4764
4765 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766}
4767
4768static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4769{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004770 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 return 0;
4772}
4773
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004774static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775 const struct audio_config *config)
4776{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004777 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004779 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4780 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781}
4782
4783static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004784 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785 audio_devices_t devices,
4786 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004787 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304788 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004789 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004790 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791{
4792 struct audio_device *adev = (struct audio_device *)dev;
4793 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004794 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004795 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004796 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304797 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304800 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4801 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804
4805 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004806
4807 if (!in) {
4808 ALOGE("failed to allocate input stream");
4809 return -ENOMEM;
4810 }
4811
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304812 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304813 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4814 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004815 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004816 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 in->stream.common.get_sample_rate = in_get_sample_rate;
4819 in->stream.common.set_sample_rate = in_set_sample_rate;
4820 in->stream.common.get_buffer_size = in_get_buffer_size;
4821 in->stream.common.get_channels = in_get_channels;
4822 in->stream.common.get_format = in_get_format;
4823 in->stream.common.set_format = in_set_format;
4824 in->stream.common.standby = in_standby;
4825 in->stream.common.dump = in_dump;
4826 in->stream.common.set_parameters = in_set_parameters;
4827 in->stream.common.get_parameters = in_get_parameters;
4828 in->stream.common.add_audio_effect = in_add_audio_effect;
4829 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4830 in->stream.set_gain = in_set_gain;
4831 in->stream.read = in_read;
4832 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4833
4834 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004835 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837 in->standby = 1;
4838 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004839 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004840 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304842 in->usecase = USECASE_AUDIO_RECORD;
4843 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4844 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4845 is_low_latency = true;
4846#if LOW_LATENCY_CAPTURE_USE_CASE
4847 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4848#endif
4849 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4850 }
4851
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004852 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004853 if (in->realtime) {
4854 in->config = pcm_config_audio_capture_rt;
4855 in->sample_rate = in->config.rate;
4856 in->af_period_multiplier = af_period_multiplier;
4857 } else {
4858 in->config = pcm_config_audio_capture;
4859 in->config.rate = config->sample_rate;
4860 in->sample_rate = config->sample_rate;
4861 in->af_period_multiplier = 1;
4862 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304863 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304865 /* restrict 24 bit capture for unprocessed source only
4866 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4867 */
4868 if (config->format == AUDIO_FORMAT_DEFAULT) {
4869 config->format = AUDIO_FORMAT_PCM_16_BIT;
4870 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4871 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4872 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4873 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4874 bool ret_error = false;
4875 in->bit_width = 24;
4876 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4877 from HAL is 24_packed and 8_24
4878 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4879 24_packed return error indicating supported format is 24_packed
4880 *> In case of any other source requesting 24 bit or float return error
4881 indicating format supported is 16 bit only.
4882
4883 on error flinger will retry with supported format passed
4884 */
4885 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4886 (source != AUDIO_SOURCE_CAMCORDER)) {
4887 config->format = AUDIO_FORMAT_PCM_16_BIT;
4888 if (config->sample_rate > 48000)
4889 config->sample_rate = 48000;
4890 ret_error = true;
4891 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4892 in->config.format = PCM_FORMAT_S24_3LE;
4893 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4894 in->config.format = PCM_FORMAT_S24_LE;
4895 } else {
4896 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4897 ret_error = true;
4898 }
4899
4900 if (ret_error) {
4901 ret = -EINVAL;
4902 goto err_open;
4903 }
4904 }
4905
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304906 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304907 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4908 (adev->mode != AUDIO_MODE_IN_CALL)) {
4909 ret = -EINVAL;
4910 goto err_open;
4911 }
4912
4913 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4914 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004915 if (config->sample_rate == 0)
4916 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4917 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4918 config->sample_rate != 8000) {
4919 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4920 ret = -EINVAL;
4921 goto err_open;
4922 }
4923 if (config->format == AUDIO_FORMAT_DEFAULT)
4924 config->format = AUDIO_FORMAT_PCM_16_BIT;
4925 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4926 config->format = AUDIO_FORMAT_PCM_16_BIT;
4927 ret = -EINVAL;
4928 goto err_open;
4929 }
4930
4931 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4932 in->config = pcm_config_afe_proxy_record;
4933 in->config.channels = channel_count;
4934 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304935 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304936 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4937 in, config, &channel_mask_updated)) {
4938 if (channel_mask_updated == true) {
4939 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4940 __func__, config->channel_mask);
4941 ret = -EINVAL;
4942 goto err_open;
4943 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304944 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004945 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004946 audio_extn_compr_cap_format_supported(config->format) &&
4947 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004948 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304949 } else if (audio_extn_cin_applicable_stream(in)) {
4950 ret = audio_extn_cin_configure_input_stream(in);
4951 if (ret)
4952 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004953 } else {
4954 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004955 if (!in->realtime) {
4956 in->format = config->format;
4957 frame_size = audio_stream_in_frame_size(&in->stream);
4958 buffer_size = get_input_buffer_size(config->sample_rate,
4959 config->format,
4960 channel_count,
4961 is_low_latency);
4962 in->config.period_size = buffer_size / frame_size;
4963 }
4964
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004965 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004966 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004967 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004968 (in->config.rate == 8000 || in->config.rate == 16000 ||
4969 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004970 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4971 voice_extn_compress_voip_open_input_stream(in);
4972 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004973 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304975 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4976 &adev->streams_input_cfg_list,
4977 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304978 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304979
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004980 /* This stream could be for sound trigger lab,
4981 get sound trigger pcm if present */
4982 audio_extn_sound_trigger_check_and_get_session(in);
4983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004985 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004986 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987
4988err_open:
4989 free(in);
4990 *stream_in = NULL;
4991 return ret;
4992}
4993
4994static void adev_close_input_stream(struct audio_hw_device *dev,
4995 struct audio_stream_in *stream)
4996{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004997 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004998 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004999 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305000
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305001 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005002
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305003 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005004 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305005
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005006 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305007 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005008 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305009 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005010 if (ret != 0)
5011 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5012 __func__, ret);
5013 } else
5014 in_standby(&stream->common);
5015
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005016 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005017 audio_extn_ssr_deinit();
5018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305020 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005021 audio_extn_compr_cap_format_supported(in->config.format))
5022 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305023
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305024 if (audio_extn_cin_attached_usecase(in->usecase))
5025 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005026
Mingming Yinfd7607b2016-01-22 12:48:44 -08005027 if (in->is_st_session) {
5028 ALOGV("%s: sound trigger pcm stop lab", __func__);
5029 audio_extn_sound_trigger_stop_lab(in);
5030 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005031 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032 return;
5033}
5034
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005035static int adev_dump(const audio_hw_device_t *device __unused,
5036 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037{
5038 return 0;
5039}
5040
5041static int adev_close(hw_device_t *device)
5042{
5043 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005044
5045 if (!adev)
5046 return 0;
5047
5048 pthread_mutex_lock(&adev_init_lock);
5049
5050 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005051 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005052 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305053 audio_extn_utils_release_streams_cfg_lists(
5054 &adev->streams_output_cfg_list,
5055 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305056 if (audio_extn_qaf_is_enabled())
5057 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005058 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005059 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005060 free(adev->snd_dev_ref_cnt);
5061 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005062 if (adev->adm_deinit)
5063 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305064 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005065 free(device);
5066 adev = NULL;
5067 }
5068 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005070 return 0;
5071}
5072
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005073/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5074 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5075 * just that it _might_ work.
5076 */
5077static int period_size_is_plausible_for_low_latency(int period_size)
5078{
5079 switch (period_size) {
5080 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005081 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005082 case 240:
5083 case 320:
5084 case 480:
5085 return 1;
5086 default:
5087 return 0;
5088 }
5089}
5090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091static int adev_open(const hw_module_t *module, const char *name,
5092 hw_device_t **device)
5093{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305094 int ret;
5095
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005096 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005097 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5098
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005099 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005100 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005101 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005102 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005103 ALOGD("%s: returning existing instance of adev", __func__);
5104 ALOGD("%s: exit", __func__);
5105 pthread_mutex_unlock(&adev_init_lock);
5106 return 0;
5107 }
5108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005109 adev = calloc(1, sizeof(struct audio_device));
5110
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005111 if (!adev) {
5112 pthread_mutex_unlock(&adev_init_lock);
5113 return -ENOMEM;
5114 }
5115
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005116 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5119 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5120 adev->device.common.module = (struct hw_module_t *)module;
5121 adev->device.common.close = adev_close;
5122
5123 adev->device.init_check = adev_init_check;
5124 adev->device.set_voice_volume = adev_set_voice_volume;
5125 adev->device.set_master_volume = adev_set_master_volume;
5126 adev->device.get_master_volume = adev_get_master_volume;
5127 adev->device.set_master_mute = adev_set_master_mute;
5128 adev->device.get_master_mute = adev_get_master_mute;
5129 adev->device.set_mode = adev_set_mode;
5130 adev->device.set_mic_mute = adev_set_mic_mute;
5131 adev->device.get_mic_mute = adev_get_mic_mute;
5132 adev->device.set_parameters = adev_set_parameters;
5133 adev->device.get_parameters = adev_get_parameters;
5134 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5135 adev->device.open_output_stream = adev_open_output_stream;
5136 adev->device.close_output_stream = adev_close_output_stream;
5137 adev->device.open_input_stream = adev_open_input_stream;
5138 adev->device.close_input_stream = adev_close_input_stream;
5139 adev->device.dump = adev_dump;
5140
5141 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005143 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005144 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005145 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005146 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005147 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005148 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005149 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005150 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005151 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005152 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005153 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005154 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305155 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305156 adev->perf_lock_opts[0] = 0x101;
5157 adev->perf_lock_opts[1] = 0x20E;
5158 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305159
5160 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5161 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005163 adev->platform = platform_init(adev);
5164 if (!adev->platform) {
5165 free(adev->snd_dev_ref_cnt);
5166 free(adev);
5167 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5168 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005169 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305170 pthread_mutex_destroy(&adev->lock);
5171 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005172 return -EINVAL;
5173 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005174
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305175 if (audio_extn_qaf_is_enabled()) {
5176 ret = audio_extn_qaf_init(adev);
5177 if (ret < 0) {
5178 free(adev);
5179 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5180 *device = NULL;
5181 pthread_mutex_unlock(&adev_init_lock);
5182 pthread_mutex_destroy(&adev->lock);
5183 return ret;
5184 }
5185
5186 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5187 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5188 }
5189
Naresh Tanniru4c630392014-05-12 01:05:52 +05305190 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5191
Eric Laurentc4aef752013-09-12 17:45:53 -07005192 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5193 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5194 if (adev->visualizer_lib == NULL) {
5195 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5196 } else {
5197 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5198 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005199 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005200 "visualizer_hal_start_output");
5201 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005202 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005203 "visualizer_hal_stop_output");
5204 }
5205 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305206 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005207 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005208 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005209 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005210
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005211 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5212 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5213 if (adev->offload_effects_lib == NULL) {
5214 ALOGE("%s: DLOPEN failed for %s", __func__,
5215 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5216 } else {
5217 ALOGV("%s: DLOPEN successful for %s", __func__,
5218 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5219 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305220 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005221 "offload_effects_bundle_hal_start_output");
5222 adev->offload_effects_stop_output =
5223 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5224 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005225 adev->offload_effects_set_hpx_state =
5226 (int (*)(bool))dlsym(adev->offload_effects_lib,
5227 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305228 adev->offload_effects_get_parameters =
5229 (void (*)(struct str_parms *, struct str_parms *))
5230 dlsym(adev->offload_effects_lib,
5231 "offload_effects_bundle_get_parameters");
5232 adev->offload_effects_set_parameters =
5233 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5234 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005235 }
5236 }
5237
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005238 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5239 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5240 if (adev->adm_lib == NULL) {
5241 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5242 } else {
5243 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5244 adev->adm_init = (adm_init_t)
5245 dlsym(adev->adm_lib, "adm_init");
5246 adev->adm_deinit = (adm_deinit_t)
5247 dlsym(adev->adm_lib, "adm_deinit");
5248 adev->adm_register_input_stream = (adm_register_input_stream_t)
5249 dlsym(adev->adm_lib, "adm_register_input_stream");
5250 adev->adm_register_output_stream = (adm_register_output_stream_t)
5251 dlsym(adev->adm_lib, "adm_register_output_stream");
5252 adev->adm_deregister_stream = (adm_deregister_stream_t)
5253 dlsym(adev->adm_lib, "adm_deregister_stream");
5254 adev->adm_request_focus = (adm_request_focus_t)
5255 dlsym(adev->adm_lib, "adm_request_focus");
5256 adev->adm_abandon_focus = (adm_abandon_focus_t)
5257 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005258 adev->adm_set_config = (adm_set_config_t)
5259 dlsym(adev->adm_lib, "adm_set_config");
5260 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5261 dlsym(adev->adm_lib, "adm_request_focus_v2");
5262 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5263 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5264 adev->adm_on_routing_change = (adm_on_routing_change_t)
5265 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005266 }
5267 }
5268
Mingming Yin514a8bc2014-07-29 15:22:21 -07005269 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005270 //initialize this to false for now,
5271 //this will be set to true through set param
5272 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005273
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005274 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005275 *device = &adev->device.common;
5276
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305277 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5278 &adev->streams_output_cfg_list,
5279 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005280
Kiran Kandi910e1862013-10-29 13:29:42 -07005281 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005282
5283 char value[PROPERTY_VALUE_MAX];
5284 int trial;
5285 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5286 trial = atoi(value);
5287 if (period_size_is_plausible_for_low_latency(trial)) {
5288 pcm_config_low_latency.period_size = trial;
5289 pcm_config_low_latency.start_threshold = trial / 4;
5290 pcm_config_low_latency.avail_min = trial / 4;
5291 configured_low_latency_capture_period_size = trial;
5292 }
5293 }
5294 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5295 trial = atoi(value);
5296 if (period_size_is_plausible_for_low_latency(trial)) {
5297 configured_low_latency_capture_period_size = trial;
5298 }
5299 }
5300
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005301 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5302 af_period_multiplier = atoi(value);
5303 if (af_period_multiplier < 0)
5304 af_period_multiplier = 2;
5305 else if (af_period_multiplier > 4)
5306 af_period_multiplier = 4;
5307
5308 ALOGV("new period_multiplier = %d", af_period_multiplier);
5309 }
5310
vivek mehta446c3962015-09-14 10:57:35 -07005311 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005312 pthread_mutex_unlock(&adev_init_lock);
5313
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005314 if (adev->adm_init)
5315 adev->adm_data = adev->adm_init();
5316
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305317 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305318 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005319 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 return 0;
5321}
5322
5323static struct hw_module_methods_t hal_module_methods = {
5324 .open = adev_open,
5325};
5326
5327struct audio_module HAL_MODULE_INFO_SYM = {
5328 .common = {
5329 .tag = HARDWARE_MODULE_TAG,
5330 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5331 .hal_api_version = HARDWARE_HAL_API_VERSION,
5332 .id = AUDIO_HARDWARE_MODULE_ID,
5333 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005334 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005335 .methods = &hal_module_methods,
5336 },
5337};