blob: 4d476da61692245830ce1a9f3410158cc422b82d [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 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530609static void check_and_set_asrc_mode(struct audio_device *adev,
610 struct audio_usecase *uc_info,
611 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612{
613 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530614 int i, num_new_devices = 0;
615 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
616 /*
617 *Split snd device for new combo use case
618 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
619 */
620 if (platform_split_snd_device(adev->platform,
621 snd_device,
622 &num_new_devices,
623 split_new_snd_devices) == 0) {
624 for (i = 0; i < num_new_devices; i++)
625 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
626 } else {
627 int new_backend_idx = platform_get_backend_index(snd_device);
628 if (((new_backend_idx == HEADPHONE_BACKEND) ||
629 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
630 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
636 int i, num_devices, ret = 0;
637 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530638
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530639 list_for_each(node, &adev->usecase_list) {
640 uc = node_to_item(node, struct audio_usecase, list);
641 curr_out = (struct stream_out*) uc->stream.out;
642 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
643 /*
644 *Split snd device for existing combo use case
645 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
646 */
647 ret = platform_split_snd_device(adev->platform,
648 uc->out_snd_device,
649 &num_devices,
650 split_snd_devices);
651 if (ret < 0 || num_devices == 0) {
652 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
653 split_snd_devices[0] = uc->out_snd_device;
654 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800655 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530656 for (i = 0; i < num_devices; i++) {
657 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
658 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
659 if((new_backend_idx == HEADPHONE_BACKEND) &&
660 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
661 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
662 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
663 __func__);
664 enable_asrc_mode(adev);
665 break;
666 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
667 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
668 (usecase_backend_idx == HEADPHONE_BACKEND)) {
669 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
670 __func__);
671 disable_audio_route(adev, uc);
672 disable_snd_device(adev, uc->out_snd_device);
673 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
674 if (new_backend_idx == DSD_NATIVE_BACKEND)
675 audio_route_apply_and_update_path(adev->audio_route,
676 "hph-true-highquality-mode");
677 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
678 (curr_out->bit_width >= 24))
679 audio_route_apply_and_update_path(adev->audio_route,
680 "hph-highquality-mode");
681 enable_asrc_mode(adev);
682 enable_snd_device(adev, uc->out_snd_device);
683 enable_audio_route(adev, uc);
684 break;
685 }
686 }
687 // reset split devices count
688 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800689 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530690 if (adev->asrc_mode_enabled)
691 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530692 }
693 }
694 }
695}
696
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700697int pcm_ioctl(struct pcm *pcm, int request, ...)
698{
699 va_list ap;
700 void * arg;
701 int pcm_fd = *(int*)pcm;
702
703 va_start(ap, request);
704 arg = va_arg(ap, void *);
705 va_end(ap);
706
707 return ioctl(pcm_fd, request, arg);
708}
709
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700710int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700714 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800715
716 if (usecase == NULL)
717 return -EINVAL;
718
719 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
720
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800721 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800723 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800725
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800726#ifdef DS1_DOLBY_DAP_ENABLED
727 audio_extn_dolby_set_dmid(adev);
728 audio_extn_dolby_set_endpoint(adev);
729#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700730 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700731 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530732 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700733 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530734 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800735 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700736 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700737 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700738 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800739 ALOGV("%s: exit", __func__);
740 return 0;
741}
742
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700743int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700744 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800745{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700747 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800748
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530749 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800750 return -EINVAL;
751
752 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 if (usecase->type == PCM_CAPTURE)
754 snd_device = usecase->in_snd_device;
755 else
756 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800757 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700758 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700759 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700760 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700761 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530762 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763 ALOGV("%s: exit", __func__);
764 return 0;
765}
766
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700767int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700768 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530770 int i, num_devices = 0;
771 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700772 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
773
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800774 if (snd_device < SND_DEVICE_MIN ||
775 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800776 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800777 return -EINVAL;
778 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700779
780 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700781
782 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
783 ALOGE("%s: Invalid sound device returned", __func__);
784 return -EINVAL;
785 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700786 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700787 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700788 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 return 0;
790 }
791
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530792
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700793 if (audio_extn_spkr_prot_is_enabled())
794 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700795
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800796 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
797 audio_extn_spkr_prot_is_enabled()) {
798 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700799 adev->snd_dev_ref_cnt[snd_device]--;
800 return -EINVAL;
801 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200802 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800803 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200805 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800806 return -EINVAL;
807 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700808 } else if (platform_split_snd_device(adev->platform,
809 snd_device,
810 &num_devices,
811 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530812 for (i = 0; i < num_devices; i++) {
813 enable_snd_device(adev, new_snd_devices[i]);
814 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800815 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700816 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530817
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530818
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530819 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
820 (audio_extn_a2dp_start_playback() < 0)) {
821 ALOGE(" fail to configure A2dp control path ");
822 return -EINVAL;
823 }
824
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700825 /* due to the possibility of calibration overwrite between listen
826 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700827 audio_extn_sound_trigger_update_device_status(snd_device,
828 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530829 audio_extn_listen_update_device_status(snd_device,
830 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700831 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700832 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700833 audio_extn_sound_trigger_update_device_status(snd_device,
834 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530835 audio_extn_listen_update_device_status(snd_device,
836 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700837 return -EINVAL;
838 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300839 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700840 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530841
842 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
843 !adev->native_playback_enabled &&
844 audio_is_true_native_stream_active(adev)) {
845 ALOGD("%s: %d: napb: enabling native mode in hardware",
846 __func__, __LINE__);
847 audio_route_apply_and_update_path(adev->audio_route,
848 "true-native-mode");
849 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800852 return 0;
853}
854
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700855int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700856 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530858 int i, num_devices = 0;
859 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700860 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
861
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800862 if (snd_device < SND_DEVICE_MIN ||
863 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800864 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800865 return -EINVAL;
866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
868 ALOGE("%s: device ref cnt is already 0", __func__);
869 return -EINVAL;
870 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700871
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700873
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700874 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
875 ALOGE("%s: Invalid sound device returned", __func__);
876 return -EINVAL;
877 }
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700880 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530881
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800882 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
883 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700884 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700885 } else if (platform_split_snd_device(adev->platform,
886 snd_device,
887 &num_devices,
888 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530889 for (i = 0; i < num_devices; i++) {
890 disable_snd_device(adev, new_snd_devices[i]);
891 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300892 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700893 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300894 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700895
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530896 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
897 audio_extn_a2dp_stop_playback();
898
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700899 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530900 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530901 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
902 adev->native_playback_enabled) {
903 ALOGD("%s: %d: napb: disabling native mode in hardware",
904 __func__, __LINE__);
905 audio_route_reset_and_update_path(adev->audio_route,
906 "true-native-mode");
907 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530908 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
909 adev->asrc_mode_enabled) {
910 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530911 disable_asrc_mode(adev);
912 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530913 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530914
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200915 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700916 audio_extn_sound_trigger_update_device_status(snd_device,
917 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530918 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800919 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922 return 0;
923}
924
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700925/*
926 legend:
927 uc - existing usecase
928 new_uc - new usecase
929 d1, d11, d2 - SND_DEVICE enums
930 a1, a2 - corresponding ANDROID device enums
931 B1, B2 - backend strings
932
933case 1
934 uc->dev d1 (a1) B1
935 new_uc->dev d1 (a1), d2 (a2) B1, B2
936
937 resolution: disable and enable uc->dev on d1
938
939case 2
940 uc->dev d1 (a1) B1
941 new_uc->dev d11 (a1) B1
942
943 resolution: need to switch uc since d1 and d11 are related
944 (e.g. speaker and voice-speaker)
945 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
946
947case 3
948 uc->dev d1 (a1) B1
949 new_uc->dev d2 (a2) B2
950
951 resolution: no need to switch uc
952
953case 4
954 uc->dev d1 (a1) B1
955 new_uc->dev d2 (a2) B1
956
957 resolution: disable enable uc-dev on d2 since backends match
958 we cannot enable two streams on two different devices if they
959 share the same backend. e.g. if offload is on speaker device using
960 QUAD_MI2S backend and a low-latency stream is started on voice-handset
961 using the same backend, offload must also be switched to voice-handset.
962
963case 5
964 uc->dev d1 (a1) B1
965 new_uc->dev d1 (a1), d2 (a2) B1
966
967 resolution: disable enable uc-dev on d2 since backends match
968 we cannot enable two streams on two different devices if they
969 share the same backend.
970
971case 6
972 uc->dev d1 (a1) B1
973 new_uc->dev d2 (a1) B2
974
975 resolution: no need to switch
976
977case 7
978 uc->dev d1 (a1), d2 (a2) B1, B2
979 new_uc->dev d1 (a1) B1
980
981 resolution: no need to switch
982
983*/
984static snd_device_t derive_playback_snd_device(void * platform,
985 struct audio_usecase *uc,
986 struct audio_usecase *new_uc,
987 snd_device_t new_snd_device)
988{
989 audio_devices_t a1 = uc->stream.out->devices;
990 audio_devices_t a2 = new_uc->stream.out->devices;
991
992 snd_device_t d1 = uc->out_snd_device;
993 snd_device_t d2 = new_snd_device;
994
995 // Treat as a special case when a1 and a2 are not disjoint
996 if ((a1 != a2) && (a1 & a2)) {
997 snd_device_t d3[2];
998 int num_devices = 0;
999 int ret = platform_split_snd_device(platform,
1000 popcount(a1) > 1 ? d1 : d2,
1001 &num_devices,
1002 d3);
1003 if (ret < 0) {
1004 if (ret != -ENOSYS) {
1005 ALOGW("%s failed to split snd_device %d",
1006 __func__,
1007 popcount(a1) > 1 ? d1 : d2);
1008 }
1009 goto end;
1010 }
1011
1012 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1013 // But if it does happen, we need to give priority to d2 if
1014 // the combo devices active on the existing usecase share a backend.
1015 // This is because we cannot have a usecase active on a combo device
1016 // and a new usecase requests one device in this combo pair.
1017 if (platform_check_backends_match(d3[0], d3[1])) {
1018 return d2; // case 5
1019 } else {
1020 return d1; // case 1
1021 }
1022 } else {
1023 if (platform_check_backends_match(d1, d2)) {
1024 return d2; // case 2, 4
1025 } else {
1026 return d1; // case 6, 3
1027 }
1028 }
1029
1030end:
1031 return d2; // return whatever was calculated before.
1032}
1033
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301035 struct audio_usecase *uc_info,
1036 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037{
1038 struct listnode *node;
1039 struct audio_usecase *usecase;
1040 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301041 snd_device_t uc_derive_snd_device;
1042 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001044 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301045 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 /*
1047 * This function is to make sure that all the usecases that are active on
1048 * the hardware codec backend are always routed to any one device that is
1049 * handled by the hardware codec.
1050 * For example, if low-latency and deep-buffer usecases are currently active
1051 * on speaker and out_set_parameters(headset) is received on low-latency
1052 * output, then we have to make sure deep-buffer is also switched to headset,
1053 * because of the limitation that both the devices cannot be enabled
1054 * at the same time as they share the same backend.
1055 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001056 /*
1057 * This call is to check if we need to force routing for a particular stream
1058 * If there is a backend configuration change for the device when a
1059 * new stream starts, then ADM needs to be closed and re-opened with the new
1060 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001061 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001062 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001063 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1064 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301065 /* For a2dp device reconfigure all active sessions
1066 * with new AFE encoder format based on a2dp state
1067 */
1068 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1069 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1070 audio_extn_a2dp_is_force_device_switch()) {
1071 force_routing = true;
1072 force_restart_session = true;
1073 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301074 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1075
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001077 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001078 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1080 switch_device[i] = false;
1081
1082 list_for_each(node, &adev->usecase_list) {
1083 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001084
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301085 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1086 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301087 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301088 platform_get_snd_device_name(usecase->out_snd_device),
1089 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301090 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1091 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1092 usecase, uc_info, snd_device);
1093 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1094 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1095 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1096 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1097 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1098 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1099 ((force_restart_session) ||
1100 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301101 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1102 __func__, use_case_table[usecase->id],
1103 platform_get_snd_device_name(usecase->out_snd_device));
1104 disable_audio_route(adev, usecase);
1105 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301106 /* Enable existing usecase on derived playback device */
1107 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301108 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 }
1111 }
1112
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301113 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1114 num_uc_to_switch);
1115
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001117 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301119 /* Make sure the previous devices to be disabled first and then enable the
1120 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 list_for_each(node, &adev->usecase_list) {
1122 usecase = node_to_item(node, struct audio_usecase, list);
1123 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001124 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 }
1126 }
1127
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001128 list_for_each(node, &adev->usecase_list) {
1129 usecase = node_to_item(node, struct audio_usecase, list);
1130 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301131 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001132 }
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 /* Re-route all the usecases on the shared backend other than the
1136 specified usecase to new snd devices */
1137 list_for_each(node, &adev->usecase_list) {
1138 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301139 /* Update the out_snd_device only before enabling the audio route */
1140 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301141 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301142 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301143 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301144 use_case_table[usecase->id],
1145 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001146 /* Update voc calibration before enabling VoIP route */
1147 if (usecase->type == VOIP_CALL)
1148 status = platform_switch_voice_call_device_post(adev->platform,
1149 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001150 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301151 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301152 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153 }
1154 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155 }
1156}
1157
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301158static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001159 struct audio_usecase *uc_info,
1160 snd_device_t snd_device)
1161{
1162 struct listnode *node;
1163 struct audio_usecase *usecase;
1164 bool switch_device[AUDIO_USECASE_MAX];
1165 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301166 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001167 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301169 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1170 snd_device);
1171 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301172
1173 /*
1174 * Make sure out devices is checked against out codec backend device and
1175 * also in devices against in codec backend. Checking out device against in
1176 * codec backend or vice versa causes issues.
1177 */
1178 if (uc_info->type == PCM_CAPTURE)
1179 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001180 /*
1181 * This function is to make sure that all the active capture usecases
1182 * are always routed to the same input sound device.
1183 * For example, if audio-record and voice-call usecases are currently
1184 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1185 * is received for voice call then we have to make sure that audio-record
1186 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1187 * because of the limitation that two devices cannot be enabled
1188 * at the same time if they share the same backend.
1189 */
1190 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1191 switch_device[i] = false;
1192
1193 list_for_each(node, &adev->usecase_list) {
1194 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301195 /*
1196 * TODO: Enhance below condition to handle BT sco/USB multi recording
1197 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001198 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001199 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301200 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301201 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301202 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301203 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001204 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001205 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1206 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001207 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001208 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001209 switch_device[usecase->id] = true;
1210 num_uc_to_switch++;
1211 }
1212 }
1213
1214 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001215 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301217 /* Make sure the previous devices to be disabled first and then enable the
1218 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001219 list_for_each(node, &adev->usecase_list) {
1220 usecase = node_to_item(node, struct audio_usecase, list);
1221 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001223 }
1224 }
1225
1226 list_for_each(node, &adev->usecase_list) {
1227 usecase = node_to_item(node, struct audio_usecase, list);
1228 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001229 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 }
1231 }
1232
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001233 /* Re-route all the usecases on the shared backend other than the
1234 specified usecase to new snd devices */
1235 list_for_each(node, &adev->usecase_list) {
1236 usecase = node_to_item(node, struct audio_usecase, list);
1237 /* Update the in_snd_device only before enabling the audio route */
1238 if (switch_device[usecase->id] ) {
1239 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001240 if (usecase->type != VOICE_CALL) {
1241 /* Update voc calibration before enabling VoIP route */
1242 if (usecase->type == VOIP_CALL)
1243 status = platform_switch_voice_call_device_post(adev->platform,
1244 usecase->out_snd_device,
1245 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301246 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001247 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001248 }
1249 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001250 }
1251}
1252
Mingming Yin3a941d42016-02-17 18:08:05 -08001253static void reset_hdmi_sink_caps(struct stream_out *out) {
1254 int i = 0;
1255
1256 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1257 out->supported_channel_masks[i] = 0;
1258 }
1259 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1260 out->supported_formats[i] = 0;
1261 }
1262 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1263 out->supported_sample_rates[i] = 0;
1264 }
1265}
1266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001268static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269{
Mingming Yin3a941d42016-02-17 18:08:05 -08001270 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001271 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Mingming Yin3a941d42016-02-17 18:08:05 -08001273 reset_hdmi_sink_caps(out);
1274
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001275 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001276 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001277 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001278 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001279 }
1280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001283 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001284 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001285 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1286 case 6:
1287 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1291 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1292 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293 break;
1294 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001295 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001296 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 break;
1298 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001299
1300 // check channel format caps
1301 i = 0;
1302 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1303 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1304 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1305 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1306 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1307 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1308 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1309 }
1310
1311 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1312 ALOGV(":%s HDMI supports DTS format", __func__);
1313 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1314 }
1315
1316 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1317 ALOGV(":%s HDMI supports DTS HD format", __func__);
1318 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1319 }
1320
1321
1322 // check sample rate caps
1323 i = 0;
1324 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1325 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1326 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1327 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1328 }
1329 }
1330
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001331 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332}
1333
Alexy Josephb1379942016-01-29 15:49:38 -08001334audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001335 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001336{
1337 struct audio_usecase *usecase;
1338 struct listnode *node;
1339
1340 list_for_each(node, &adev->usecase_list) {
1341 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001342 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001343 ALOGV("%s: usecase id %d", __func__, usecase->id);
1344 return usecase->id;
1345 }
1346 }
1347 return USECASE_INVALID;
1348}
1349
Alexy Josephb1379942016-01-29 15:49:38 -08001350struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001351 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352{
1353 struct audio_usecase *usecase;
1354 struct listnode *node;
1355
1356 list_for_each(node, &adev->usecase_list) {
1357 usecase = node_to_item(node, struct audio_usecase, list);
1358 if (usecase->id == uc_id)
1359 return usecase;
1360 }
1361 return NULL;
1362}
1363
Dhananjay Kumard4833242016-10-06 22:09:12 +05301364struct stream_in *get_next_active_input(const struct audio_device *adev)
1365{
1366 struct audio_usecase *usecase;
1367 struct listnode *node;
1368
1369 list_for_each_reverse(node, &adev->usecase_list) {
1370 usecase = node_to_item(node, struct audio_usecase, list);
1371 if (usecase->type == PCM_CAPTURE)
1372 return usecase->stream.in;
1373 }
1374 return NULL;
1375}
1376
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301377/*
1378 * is a true native playback active
1379 */
1380bool audio_is_true_native_stream_active(struct audio_device *adev)
1381{
1382 bool active = false;
1383 int i = 0;
1384 struct listnode *node;
1385
1386 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1387 ALOGV("%s:napb: not in true mode or non hdphones device",
1388 __func__);
1389 active = false;
1390 goto exit;
1391 }
1392
1393 list_for_each(node, &adev->usecase_list) {
1394 struct audio_usecase *uc;
1395 uc = node_to_item(node, struct audio_usecase, list);
1396 struct stream_out *curr_out =
1397 (struct stream_out*) uc->stream.out;
1398
1399 if (curr_out && PCM_PLAYBACK == uc->type) {
1400 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1401 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1402 uc->id, curr_out->sample_rate,
1403 curr_out->bit_width,
1404 platform_get_snd_device_name(uc->out_snd_device));
1405
1406 if (is_offload_usecase(uc->id) &&
1407 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1408 active = true;
1409 ALOGD("%s:napb:native stream detected", __func__);
1410 }
1411 }
1412 }
1413exit:
1414 return active;
1415}
1416
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301417/*
1418 * if native DSD playback active
1419 */
1420bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1421{
1422 bool active = false;
1423 struct listnode *node = NULL;
1424 struct audio_usecase *uc = NULL;
1425 struct stream_out *curr_out = NULL;
1426
1427 list_for_each(node, &adev->usecase_list) {
1428 uc = node_to_item(node, struct audio_usecase, list);
1429 curr_out = (struct stream_out*) uc->stream.out;
1430
1431 if (curr_out && PCM_PLAYBACK == uc->type &&
1432 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1433 active = true;
1434 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301435 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301436 }
1437 }
1438 return active;
1439}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301440
1441static bool force_device_switch(struct audio_usecase *usecase)
1442{
1443 bool ret = false;
1444 bool is_it_true_mode = false;
1445
1446 if (is_offload_usecase(usecase->id) &&
1447 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001448 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1449 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1450 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301451 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1452 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1453 (!is_it_true_mode && adev->native_playback_enabled)){
1454 ret = true;
1455 ALOGD("napb: time to toggle native mode");
1456 }
1457 }
1458
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301459 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301460 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1461 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301462 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001463 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301464 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301465 ALOGD("Force a2dp device switch to update new encoder config");
1466 ret = true;
1467 }
1468
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301469 return ret;
1470}
1471
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001472int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001474 snd_device_t out_snd_device = SND_DEVICE_NONE;
1475 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 struct audio_usecase *usecase = NULL;
1477 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001478 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001479 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001480 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301483 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1484
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 usecase = get_usecase_from_list(adev, uc_id);
1486 if (usecase == NULL) {
1487 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1488 return -EINVAL;
1489 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001491 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001492 (usecase->type == VOIP_CALL) ||
1493 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301494 if(usecase->stream.out == NULL) {
1495 ALOGE("%s: stream.out is NULL", __func__);
1496 return -EINVAL;
1497 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001498 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001499 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001500 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 usecase->devices = usecase->stream.out->devices;
1502 } else {
1503 /*
1504 * If the voice call is active, use the sound devices of voice call usecase
1505 * so that it would not result any device switch. All the usecases will
1506 * be switched to new device when select_devices() is called for voice call
1507 * usecase. This is to avoid switching devices for voice call when
1508 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001509 * choose voice call device only if the use case device is
1510 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001511 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001512 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001513 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001514 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001515 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1516 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301517 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1518 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001519 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 in_snd_device = vc_usecase->in_snd_device;
1521 out_snd_device = vc_usecase->out_snd_device;
1522 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001523 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001524 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001525 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh02ef86f2017-04-21 15:36:04 +08001526 if (usecase->stream.out != NULL) {
1527 out_snd_device_backend_match = platform_check_backends_match(
1528 voip_usecase->out_snd_device,
1529 platform_get_output_snd_device(
1530 adev->platform,
1531 usecase->stream.out));
1532 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001533 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001534 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1535 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001536 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001537 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001538 in_snd_device = voip_usecase->in_snd_device;
1539 out_snd_device = voip_usecase->out_snd_device;
1540 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001541 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001542 hfp_ucid = audio_extn_hfp_get_usecase();
1543 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001544 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001545 in_snd_device = hfp_usecase->in_snd_device;
1546 out_snd_device = hfp_usecase->out_snd_device;
1547 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001548 }
1549 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301550 if (usecase->stream.out == NULL) {
1551 ALOGE("%s: stream.out is NULL", __func__);
1552 return -EINVAL;
1553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 usecase->devices = usecase->stream.out->devices;
1555 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001556 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001558 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001559 if (usecase->stream.out == adev->primary_output &&
1560 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001561 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001562 select_devices(adev, adev->active_input->usecase);
1563 }
1564 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301566 if (usecase->stream.in == NULL) {
1567 ALOGE("%s: stream.in is NULL", __func__);
1568 return -EINVAL;
1569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 usecase->devices = usecase->stream.in->device;
1571 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001572 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001573 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001574 if (adev->active_input &&
1575 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301576 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1577 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1578 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001579 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001580 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001581 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1582 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001583 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001584 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001585 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001586 }
1587 }
1588
1589 if (out_snd_device == usecase->out_snd_device &&
1590 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301591
1592 if (!force_device_switch(usecase))
1593 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001594 }
1595
sangwoobc677242013-08-08 16:53:43 +09001596 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001597 out_snd_device, platform_get_snd_device_name(out_snd_device),
1598 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 /*
1601 * Limitation: While in call, to do a device switch we need to disable
1602 * and enable both RX and TX devices though one of them is same as current
1603 * device.
1604 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001605 if ((usecase->type == VOICE_CALL) &&
1606 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1607 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001608 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001609 }
1610
1611 if (((usecase->type == VOICE_CALL) ||
1612 (usecase->type == VOIP_CALL)) &&
1613 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1614 /* Disable sidetone only if voice/voip call already exists */
1615 if (voice_is_call_state_active(adev) ||
1616 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001617 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001618
1619 /* Disable aanc only if voice call exists */
1620 if (voice_is_call_state_active(adev))
1621 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001622 }
1623
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624 /* Disable current sound devices */
1625 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001626 disable_audio_route(adev, usecase);
1627 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628 }
1629
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001631 disable_audio_route(adev, usecase);
1632 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 }
1634
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001635 /* Applicable only on the targets that has external modem.
1636 * New device information should be sent to modem before enabling
1637 * the devices to reduce in-call device switch time.
1638 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001639 if ((usecase->type == VOICE_CALL) &&
1640 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1641 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001642 status = platform_switch_voice_call_enable_device_config(adev->platform,
1643 out_snd_device,
1644 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001645 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001646
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 /* Enable new sound devices */
1648 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001649 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301650 if (platform_check_codec_asrc_support(adev->platform))
1651 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001652 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 }
1654
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001655 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301656 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001657 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001658 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659
Avinash Vaish71a8b972014-07-24 15:36:33 +05301660 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001661 status = platform_switch_voice_call_device_post(adev->platform,
1662 out_snd_device,
1663 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301664 enable_audio_route_for_voice_usecases(adev, usecase);
1665 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001666
sangwoo170731f2013-06-08 15:36:36 +09001667 usecase->in_snd_device = in_snd_device;
1668 usecase->out_snd_device = out_snd_device;
1669
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301670 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1671 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301672 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001673 if ((24 == usecase->stream.out->bit_width) &&
1674 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1675 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1676 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1677 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1678 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1679 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1680 /*
1681 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1682 * configured device sample rate, if not update the COPP rate to be equal to the
1683 * device sample rate, else open COPP at stream sample rate
1684 */
1685 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1686 usecase->stream.out->sample_rate,
1687 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301688 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1689 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001690 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1691 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1692 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1693 }
1694
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001695 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001696 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001697 audio_extn_gef_notify_device_config(
1698 usecase->stream.out->devices,
1699 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001700 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001701 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001702 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301703 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001704 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001705
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001706 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001707 /* Enable aanc only if voice call exists */
1708 if (voice_is_call_state_active(adev))
1709 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1710
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001711 /* Enable sidetone only if other voice/voip call already exists */
1712 if (voice_is_call_state_active(adev) ||
1713 voice_extn_compress_voip_is_started(adev))
1714 voice_set_sidetone(adev, out_snd_device, true);
1715 }
1716
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001717 /* Applicable only on the targets that has external modem.
1718 * Enable device command should be sent to modem only after
1719 * enabling voice call mixer controls
1720 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001721 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001722 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1723 out_snd_device,
1724 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301725 ALOGD("%s: done",__func__);
1726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 return status;
1728}
1729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730static int stop_input_stream(struct stream_in *in)
1731{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301732 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733 struct audio_usecase *uc_info;
1734 struct audio_device *adev = in->dev;
1735
Eric Laurent994a6932013-07-17 11:51:42 -07001736 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001737 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 uc_info = get_usecase_from_list(adev, in->usecase);
1739 if (uc_info == NULL) {
1740 ALOGE("%s: Could not find the usecase (%d) in the list",
1741 __func__, in->usecase);
1742 return -EINVAL;
1743 }
1744
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001745 /* Close in-call recording streams */
1746 voice_check_and_stop_incall_rec_usecase(adev, in);
1747
Eric Laurent150dbfe2013-02-27 14:31:02 -08001748 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001749 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750
1751 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001752 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001754 list_remove(&uc_info->list);
1755 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001757 adev->active_input = get_next_active_input(adev);
1758
Eric Laurent994a6932013-07-17 11:51:42 -07001759 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 return ret;
1761}
1762
1763int start_input_stream(struct stream_in *in)
1764{
1765 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001766 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 struct audio_usecase *uc_info;
1768 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301769 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Mingming Yin2664a5b2015-09-03 10:53:11 -07001771 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1772 if (get_usecase_from_list(adev, usecase) == NULL)
1773 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301774 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1775 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001776
Naresh Tanniru80659832014-06-04 18:17:56 +05301777
1778 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301779 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301780 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301781 goto error_config;
1782 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301783
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001784 /* Check if source matches incall recording usecase criteria */
1785 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1786 if (ret)
1787 goto error_config;
1788 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001789 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1790
1791 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1792 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1793 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001794 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001795 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001796
Eric Laurentb23d5282013-05-14 15:27:20 -07001797 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 if (in->pcm_device_id < 0) {
1799 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1800 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001801 ret = -EINVAL;
1802 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001804
1805 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001807
1808 if (!uc_info) {
1809 ret = -ENOMEM;
1810 goto error_config;
1811 }
1812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 uc_info->id = in->usecase;
1814 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001815 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816 uc_info->devices = in->device;
1817 uc_info->in_snd_device = SND_DEVICE_NONE;
1818 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001820 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301821 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1822 adev->perf_lock_opts,
1823 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301826 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1827 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001828
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301829 if (audio_extn_cin_attached_usecase(in->usecase)) {
1830 ret = audio_extn_cin_start_input_stream(in);
1831 if (ret)
1832 goto error_open;
1833 else
1834 goto done_open;
1835 }
1836
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001837 unsigned int flags = PCM_IN;
1838 unsigned int pcm_open_retry_count = 0;
1839
1840 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1841 flags |= PCM_MMAP | PCM_NOIRQ;
1842 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001843 } else if (in->realtime) {
1844 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001845 }
1846
1847 while (1) {
1848 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1849 flags, &in->config);
1850 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1851 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1852 if (in->pcm != NULL) {
1853 pcm_close(in->pcm);
1854 in->pcm = NULL;
1855 }
1856 if (pcm_open_retry_count-- == 0) {
1857 ret = -EIO;
1858 goto error_open;
1859 }
1860 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1861 continue;
1862 }
1863 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001865
1866 ALOGV("%s: pcm_prepare", __func__);
1867 ret = pcm_prepare(in->pcm);
1868 if (ret < 0) {
1869 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1870 pcm_close(in->pcm);
1871 in->pcm = NULL;
1872 goto error_open;
1873 }
1874
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001875 register_in_stream(in);
1876 if (in->realtime) {
1877 ret = pcm_start(in->pcm);
1878 if (ret < 0)
1879 goto error_open;
1880 }
1881
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301882done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301883 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001884 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001885
Eric Laurentc8400632013-02-14 19:04:54 -08001886 return ret;
1887
1888error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301889 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001891error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301892 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301893 /*
1894 * sleep 50ms to allow sufficient time for kernel
1895 * drivers to recover incases like SSR.
1896 */
1897 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001899
1900 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901}
1902
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001903void lock_input_stream(struct stream_in *in)
1904{
1905 pthread_mutex_lock(&in->pre_lock);
1906 pthread_mutex_lock(&in->lock);
1907 pthread_mutex_unlock(&in->pre_lock);
1908}
1909
1910void lock_output_stream(struct stream_out *out)
1911{
1912 pthread_mutex_lock(&out->pre_lock);
1913 pthread_mutex_lock(&out->lock);
1914 pthread_mutex_unlock(&out->pre_lock);
1915}
1916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917/* must be called with out->lock locked */
1918static int send_offload_cmd_l(struct stream_out* out, int command)
1919{
1920 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1921
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001922 if (!cmd) {
1923 ALOGE("failed to allocate mem for command 0x%x", command);
1924 return -ENOMEM;
1925 }
1926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001927 ALOGVV("%s %d", __func__, command);
1928
1929 cmd->cmd = command;
1930 list_add_tail(&out->offload_cmd_list, &cmd->node);
1931 pthread_cond_signal(&out->offload_cond);
1932 return 0;
1933}
1934
1935/* must be called iwth out->lock locked */
1936static void stop_compressed_output_l(struct stream_out *out)
1937{
1938 out->offload_state = OFFLOAD_STATE_IDLE;
1939 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001940 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001941 if (out->compr != NULL) {
1942 compress_stop(out->compr);
1943 while (out->offload_thread_blocked) {
1944 pthread_cond_wait(&out->cond, &out->lock);
1945 }
1946 }
1947}
1948
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001949bool is_offload_usecase(audio_usecase_t uc_id)
1950{
1951 unsigned int i;
1952 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1953 if (uc_id == offload_usecases[i])
1954 return true;
1955 }
1956 return false;
1957}
1958
Dhananjay Kumarac341582017-02-23 23:42:25 +05301959static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001960{
vivek mehta446c3962015-09-14 10:57:35 -07001961 audio_usecase_t ret_uc = USECASE_INVALID;
1962 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001963 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001964 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301965 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001966 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1967 else
1968 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001969
vivek mehta446c3962015-09-14 10:57:35 -07001970 pthread_mutex_lock(&adev->lock);
1971 if (get_usecase_from_list(adev, ret_uc) != NULL)
1972 ret_uc = USECASE_INVALID;
1973 pthread_mutex_unlock(&adev->lock);
1974
1975 return ret_uc;
1976 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001977
1978 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001979 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1980 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1981 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1982 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001983 break;
1984 }
1985 }
vivek mehta446c3962015-09-14 10:57:35 -07001986
1987 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1988 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001989}
1990
1991static void free_offload_usecase(struct audio_device *adev,
1992 audio_usecase_t uc_id)
1993{
vivek mehta446c3962015-09-14 10:57:35 -07001994 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001995 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001996
1997 if (!adev->multi_offload_enable)
1998 return;
1999
2000 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2001 if (offload_usecases[offload_uc_index] == uc_id) {
2002 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002003 break;
2004 }
2005 }
2006 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2007}
2008
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009static void *offload_thread_loop(void *context)
2010{
2011 struct stream_out *out = (struct stream_out *) context;
2012 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002013 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002014
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002015 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2016 set_sched_policy(0, SP_FOREGROUND);
2017 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2018
2019 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002020 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021 for (;;) {
2022 struct offload_cmd *cmd = NULL;
2023 stream_callback_event_t event;
2024 bool send_callback = false;
2025
2026 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2027 __func__, list_empty(&out->offload_cmd_list),
2028 out->offload_state);
2029 if (list_empty(&out->offload_cmd_list)) {
2030 ALOGV("%s SLEEPING", __func__);
2031 pthread_cond_wait(&out->offload_cond, &out->lock);
2032 ALOGV("%s RUNNING", __func__);
2033 continue;
2034 }
2035
2036 item = list_head(&out->offload_cmd_list);
2037 cmd = node_to_item(item, struct offload_cmd, node);
2038 list_remove(item);
2039
2040 ALOGVV("%s STATE %d CMD %d out->compr %p",
2041 __func__, out->offload_state, cmd->cmd, out->compr);
2042
2043 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2044 free(cmd);
2045 break;
2046 }
2047
2048 if (out->compr == NULL) {
2049 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002050 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 pthread_cond_signal(&out->cond);
2052 continue;
2053 }
2054 out->offload_thread_blocked = true;
2055 pthread_mutex_unlock(&out->lock);
2056 send_callback = false;
2057 switch(cmd->cmd) {
2058 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002059 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002061 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 send_callback = true;
2063 event = STREAM_CBK_EVENT_WRITE_READY;
2064 break;
2065 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002066 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302067 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002068 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302069 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002070 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302071 if (ret < 0)
2072 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302073 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302074 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002075 compress_drain(out->compr);
2076 else
2077 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302078 if (ret != -ENETRESET) {
2079 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302080 pthread_mutex_lock(&out->lock);
2081 out->send_new_metadata = 1;
2082 out->send_next_track_params = true;
2083 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302084 event = STREAM_CBK_EVENT_DRAIN_READY;
2085 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2086 } else
2087 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002088 break;
2089 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002090 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002092 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 send_callback = true;
2094 event = STREAM_CBK_EVENT_DRAIN_READY;
2095 break;
2096 default:
2097 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2098 break;
2099 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002100 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 out->offload_thread_blocked = false;
2102 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002103 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002104 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002106 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002107 free(cmd);
2108 }
2109
2110 pthread_cond_signal(&out->cond);
2111 while (!list_empty(&out->offload_cmd_list)) {
2112 item = list_head(&out->offload_cmd_list);
2113 list_remove(item);
2114 free(node_to_item(item, struct offload_cmd, node));
2115 }
2116 pthread_mutex_unlock(&out->lock);
2117
2118 return NULL;
2119}
2120
2121static int create_offload_callback_thread(struct stream_out *out)
2122{
2123 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2124 list_init(&out->offload_cmd_list);
2125 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2126 offload_thread_loop, out);
2127 return 0;
2128}
2129
2130static int destroy_offload_callback_thread(struct stream_out *out)
2131{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002132 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 stop_compressed_output_l(out);
2134 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2135
2136 pthread_mutex_unlock(&out->lock);
2137 pthread_join(out->offload_thread, (void **) NULL);
2138 pthread_cond_destroy(&out->offload_cond);
2139
2140 return 0;
2141}
2142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143static int stop_output_stream(struct stream_out *out)
2144{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302145 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 struct audio_usecase *uc_info;
2147 struct audio_device *adev = out->dev;
2148
Eric Laurent994a6932013-07-17 11:51:42 -07002149 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002150 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 uc_info = get_usecase_from_list(adev, out->usecase);
2152 if (uc_info == NULL) {
2153 ALOGE("%s: Could not find the usecase (%d) in the list",
2154 __func__, out->usecase);
2155 return -EINVAL;
2156 }
2157
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002158 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302159 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002160 if (adev->visualizer_stop_output != NULL)
2161 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002162
2163 audio_extn_dts_remove_state_notifier_node(out->usecase);
2164
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002165 if (adev->offload_effects_stop_output != NULL)
2166 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2167 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002168
Eric Laurent150dbfe2013-02-27 14:31:02 -08002169 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002170 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171
2172 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002173 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002175 list_remove(&uc_info->list);
2176 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002178 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302179 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002180 ALOGV("Disable passthrough , reset mixer to pcm");
2181 /* NO_PASSTHROUGH */
2182 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002183 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002184 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2185 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002186
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302187 /* Must be called after removing the usecase from list */
2188 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302189 audio_extn_keep_alive_start();
2190
Eric Laurent994a6932013-07-17 11:51:42 -07002191 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 return ret;
2193}
2194
2195int start_output_stream(struct stream_out *out)
2196{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 struct audio_usecase *uc_info;
2199 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302200 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002201 char mixer_ctl_name[128];
2202 struct mixer_ctl *ctl = NULL;
2203 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002205 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2206 ret = -EINVAL;
2207 goto error_config;
2208 }
2209
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302210 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2211 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2212 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302213
Naresh Tanniru80659832014-06-04 18:17:56 +05302214 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302215 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302216 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302217 goto error_config;
2218 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302219
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302220 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2221 if (!audio_extn_a2dp_is_ready()) {
2222 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2223 //combo usecase just by pass a2dp
2224 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2225 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2226 } else {
2227 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2228 ret = -EAGAIN;
2229 goto error_config;
2230 }
2231 }
2232 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002233 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 if (out->pcm_device_id < 0) {
2235 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2236 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002237 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002238 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 }
2240
2241 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002242
2243 if (!uc_info) {
2244 ret = -ENOMEM;
2245 goto error_config;
2246 }
2247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 uc_info->id = out->usecase;
2249 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002250 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002251 uc_info->devices = out->devices;
2252 uc_info->in_snd_device = SND_DEVICE_NONE;
2253 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002254 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302256 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2257 adev->perf_lock_opts,
2258 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302259
2260 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2261 audio_extn_keep_alive_stop();
2262 if (audio_extn_passthru_is_enabled() &&
2263 audio_extn_passthru_is_passthrough_stream(out)) {
2264 audio_extn_passthru_on_start(out);
2265 audio_extn_passthru_update_stream_configuration(adev, out);
2266 }
2267 }
2268
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002269 select_devices(adev, out->usecase);
2270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002271 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2272 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002273 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002274 unsigned int flags = PCM_OUT;
2275 unsigned int pcm_open_retry_count = 0;
2276 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2277 flags |= PCM_MMAP | PCM_NOIRQ;
2278 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002279 } else if (out->realtime) {
2280 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002281 } else
2282 flags |= PCM_MONOTONIC;
2283
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002284 if ((adev->vr_audio_mode_enabled) &&
2285 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2286 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2287 "PCM_Dev %d Topology", out->pcm_device_id);
2288 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2289 if (!ctl) {
2290 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2291 __func__, mixer_ctl_name);
2292 } else {
2293 //if success use ULLPP
2294 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2295 __func__, mixer_ctl_name, out->pcm_device_id);
2296 //There is a still a possibility that some sessions
2297 // that request for FAST|RAW when 3D audio is active
2298 //can go through ULLPP. Ideally we expects apps to
2299 //listen to audio focus and stop concurrent playback
2300 //Also, we will look for mode flag (voice_in_communication)
2301 //before enabling the realtime flag.
2302 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2303 }
2304 }
2305
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002306 while (1) {
2307 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2308 flags, &out->config);
2309 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2310 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2311 if (out->pcm != NULL) {
2312 pcm_close(out->pcm);
2313 out->pcm = NULL;
2314 }
2315 if (pcm_open_retry_count-- == 0) {
2316 ret = -EIO;
2317 goto error_open;
2318 }
2319 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2320 continue;
2321 }
2322 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002323 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002324
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002325 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2326 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002327
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002328 ALOGV("%s: pcm_prepare", __func__);
2329 if (pcm_is_ready(out->pcm)) {
2330 ret = pcm_prepare(out->pcm);
2331 if (ret < 0) {
2332 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2333 pcm_close(out->pcm);
2334 out->pcm = NULL;
2335 goto error_open;
2336 }
2337 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302338 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2339 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002341 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2342 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002344 out->compr = compress_open(adev->snd_card,
2345 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 COMPRESS_IN, &out->compr_config);
2347 if (out->compr && !is_compress_ready(out->compr)) {
2348 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2349 compress_close(out->compr);
2350 out->compr = NULL;
2351 ret = -EIO;
2352 goto error_open;
2353 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302354 /* compress_open sends params of the track, so reset the flag here */
2355 out->is_compr_metadata_avail = false;
2356
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 if (out->offload_callback)
2358 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002359
Fred Oh3f43e742015-03-04 18:42:34 -08002360 /* Since small bufs uses blocking writes, a write will be blocked
2361 for the default max poll time (20s) in the event of an SSR.
2362 Reduce the poll time to observe and deal with SSR faster.
2363 */
Ashish Jain5106d362016-05-11 19:23:33 +05302364 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002365 compress_set_max_poll_wait(out->compr, 1000);
2366 }
2367
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002368 audio_extn_dts_create_state_notifier_node(out->usecase);
2369 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2370 popcount(out->channel_mask),
2371 out->playback_started);
2372
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002373#ifdef DS1_DOLBY_DDP_ENABLED
2374 if (audio_extn_is_dolby_format(out->format))
2375 audio_extn_dolby_send_ddp_endp_params(adev);
2376#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302377 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2378 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002379 if (adev->visualizer_start_output != NULL)
2380 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2381 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302382 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002383 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002384 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002386
2387 if (ret == 0) {
2388 register_out_stream(out);
2389 if (out->realtime) {
2390 ret = pcm_start(out->pcm);
2391 if (ret < 0)
2392 goto error_open;
2393 }
2394 }
2395
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302396 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002397 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002398
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002399 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302401 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002403error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302404 /*
2405 * sleep 50ms to allow sufficient time for kernel
2406 * drivers to recover incases like SSR.
2407 */
2408 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002409 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410}
2411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412static int check_input_parameters(uint32_t sample_rate,
2413 audio_format_t format,
2414 int channel_count)
2415{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002416 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302418 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2419 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2420 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002421 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302422 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002423
2424 switch (channel_count) {
2425 case 1:
2426 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302427 case 3:
2428 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002429 case 6:
2430 break;
2431 default:
2432 ret = -EINVAL;
2433 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434
2435 switch (sample_rate) {
2436 case 8000:
2437 case 11025:
2438 case 12000:
2439 case 16000:
2440 case 22050:
2441 case 24000:
2442 case 32000:
2443 case 44100:
2444 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302445 case 96000:
2446 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447 break;
2448 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002449 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 }
2451
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002452 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453}
2454
2455static size_t get_input_buffer_size(uint32_t sample_rate,
2456 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002457 int channel_count,
2458 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459{
2460 size_t size = 0;
2461
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002462 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2463 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002465 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002466 if (is_low_latency)
2467 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302468
2469 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002471 /* make sure the size is multiple of 32 bytes
2472 * At 48 kHz mono 16-bit PCM:
2473 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2474 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2475 */
2476 size += 0x1f;
2477 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002478
2479 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480}
2481
Ashish Jain058165c2016-09-28 23:18:48 +05302482static size_t get_output_period_size(uint32_t sample_rate,
2483 audio_format_t format,
2484 int channel_count,
2485 int duration /*in millisecs*/)
2486{
2487 size_t size = 0;
2488 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2489
2490 if ((duration == 0) || (sample_rate == 0) ||
2491 (bytes_per_sample == 0) || (channel_count == 0)) {
2492 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2493 bytes_per_sample, channel_count);
2494 return -EINVAL;
2495 }
2496
2497 size = (sample_rate *
2498 duration *
2499 bytes_per_sample *
2500 channel_count) / 1000;
2501 /*
2502 * To have same PCM samples for all channels, the buffer size requires to
2503 * be multiple of (number of channels * bytes per sample)
2504 * For writes to succeed, the buffer must be written at address which is multiple of 32
2505 */
2506 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2507
2508 return (size/(channel_count * bytes_per_sample));
2509}
2510
Ashish Jain5106d362016-05-11 19:23:33 +05302511static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2512{
2513 uint64_t actual_frames_rendered = 0;
2514 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2515
2516 /* This adjustment accounts for buffering after app processor.
2517 * It is based on estimated DSP latency per use case, rather than exact.
2518 */
2519 int64_t platform_latency = platform_render_latency(out->usecase) *
2520 out->sample_rate / 1000000LL;
2521
2522 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2523 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2524 * hence only estimate.
2525 */
2526 int64_t signed_frames = out->written - kernel_buffer_size;
2527
2528 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2529
2530 if (signed_frames > 0)
2531 actual_frames_rendered = signed_frames;
2532
2533 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2534 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2535 (long long int)out->written, (int)kernel_buffer_size,
2536 audio_bytes_per_sample(out->compr_config.codec->format),
2537 popcount(out->channel_mask));
2538
2539 return actual_frames_rendered;
2540}
2541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2543{
2544 struct stream_out *out = (struct stream_out *)stream;
2545
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547}
2548
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002549static int out_set_sample_rate(struct audio_stream *stream __unused,
2550 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551{
2552 return -ENOSYS;
2553}
2554
2555static size_t out_get_buffer_size(const struct audio_stream *stream)
2556{
2557 struct stream_out *out = (struct stream_out *)stream;
2558
Dhananjay Kumarac341582017-02-23 23:42:25 +05302559 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002560 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002561 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2562 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302563 else if (is_offload_usecase(out->usecase) &&
2564 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302565 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002566
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002567 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002568 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569}
2570
2571static uint32_t out_get_channels(const struct audio_stream *stream)
2572{
2573 struct stream_out *out = (struct stream_out *)stream;
2574
2575 return out->channel_mask;
2576}
2577
2578static audio_format_t out_get_format(const struct audio_stream *stream)
2579{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002580 struct stream_out *out = (struct stream_out *)stream;
2581
2582 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583}
2584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002585static int out_set_format(struct audio_stream *stream __unused,
2586 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 return -ENOSYS;
2589}
2590
2591static int out_standby(struct audio_stream *stream)
2592{
2593 struct stream_out *out = (struct stream_out *)stream;
2594 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302596 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2597 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002599 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002601 if (adev->adm_deregister_stream)
2602 adev->adm_deregister_stream(adev->adm_data, out->handle);
2603
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002604 if (is_offload_usecase(out->usecase))
2605 stop_compressed_output_l(out);
2606
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002607 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002609 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2610 voice_extn_compress_voip_close_output_stream(stream);
2611 pthread_mutex_unlock(&adev->lock);
2612 pthread_mutex_unlock(&out->lock);
2613 ALOGD("VOIP output entered standby");
2614 return 0;
2615 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->pcm) {
2617 pcm_close(out->pcm);
2618 out->pcm = NULL;
2619 }
2620 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002621 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302622 out->send_next_track_params = false;
2623 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002624 out->gapless_mdata.encoder_delay = 0;
2625 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002626 if (out->compr != NULL) {
2627 compress_close(out->compr);
2628 out->compr = NULL;
2629 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002632 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 }
2634 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302635 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 return 0;
2637}
2638
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002639static int out_dump(const struct audio_stream *stream __unused,
2640 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641{
2642 return 0;
2643}
2644
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002645static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2646{
2647 int ret = 0;
2648 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002649
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002650 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002651 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002652 return -EINVAL;
2653 }
2654
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302655 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002656
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002657 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2658 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302659 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002660 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002661 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2662 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302663 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002664 }
2665
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002666 ALOGV("%s new encoder delay %u and padding %u", __func__,
2667 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2668
2669 return 0;
2670}
2671
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002672static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2673{
2674 return out == adev->primary_output || out == adev->voice_tx_output;
2675}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680 struct audio_device *adev = out->dev;
2681 struct str_parms *parms;
2682 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002683 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
sangwoobc677242013-08-08 16:53:43 +09002685 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002686 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302688 if (!parms)
2689 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002690 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2691 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002693 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002694 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002696 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002697 * When HDMI cable is unplugged the music playback is paused and
2698 * the policy manager sends routing=0. But the audioflinger continues
2699 * to write data until standby time (3sec). As the HDMI core is
2700 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002701 * Avoid this by routing audio to speaker until standby.
2702 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002703 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2704 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302705 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002706 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2707 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002708 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302709 /*
2710 * When A2DP is disconnected the
2711 * music playback is paused and the policy manager sends routing=0
2712 * But the audioflingercontinues to write data until standby time
2713 * (3sec). As BT is turned off, the write gets blocked.
2714 * Avoid this by routing audio to speaker until standby.
2715 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002716 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302717 (val == AUDIO_DEVICE_NONE)) {
2718 val = AUDIO_DEVICE_OUT_SPEAKER;
2719 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302720 /* To avoid a2dp to sco overlapping / BT device improper state
2721 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302722 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302723 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2724 if (!audio_extn_a2dp_is_ready()) {
2725 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2726 //combo usecase just by pass a2dp
2727 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2728 val = AUDIO_DEVICE_OUT_SPEAKER;
2729 } else {
2730 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2731 /* update device to a2dp and don't route as BT returned error
2732 * However it is still possible a2dp routing called because
2733 * of current active device disconnection (like wired headset)
2734 */
2735 out->devices = val;
2736 pthread_mutex_unlock(&out->lock);
2737 pthread_mutex_unlock(&adev->lock);
2738 goto error;
2739 }
2740 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002742 /*
2743 * select_devices() call below switches all the usecases on the same
2744 * backend to the new device. Refer to check_usecases_codec_backend() in
2745 * the select_devices(). But how do we undo this?
2746 *
2747 * For example, music playback is active on headset (deep-buffer usecase)
2748 * and if we go to ringtones and select a ringtone, low-latency usecase
2749 * will be started on headset+speaker. As we can't enable headset+speaker
2750 * and headset devices at the same time, select_devices() switches the music
2751 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2752 * So when the ringtone playback is completed, how do we undo the same?
2753 *
2754 * We are relying on the out_set_parameters() call on deep-buffer output,
2755 * once the ringtone playback is ended.
2756 * NOTE: We should not check if the current devices are same as new devices.
2757 * Because select_devices() must be called to switch back the music
2758 * playback to headset.
2759 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002760 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002761 audio_devices_t new_dev = val;
2762 bool same_dev = out->devices == new_dev;
2763 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002765 if (output_drives_call(adev, out)) {
2766 if(!voice_is_in_call(adev)) {
2767 if (adev->mode == AUDIO_MODE_IN_CALL) {
2768 adev->current_call_output = out;
2769 ret = voice_start_call(adev);
2770 }
2771 } else {
2772 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002773 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002774 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002775 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002776
2777 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002778 if (!same_dev) {
2779 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302780 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2781 adev->perf_lock_opts,
2782 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002783 if (adev->adm_on_routing_change)
2784 adev->adm_on_routing_change(adev->adm_data,
2785 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002786 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002787 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302788 if (!same_dev)
2789 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002790 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002791 }
2792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002794 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002796
2797 if (out == adev->primary_output) {
2798 pthread_mutex_lock(&adev->lock);
2799 audio_extn_set_parameters(adev, parms);
2800 pthread_mutex_unlock(&adev->lock);
2801 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002802 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002803 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002804 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002805
2806 audio_extn_dts_create_state_notifier_node(out->usecase);
2807 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2808 popcount(out->channel_mask),
2809 out->playback_started);
2810
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002811 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002812 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002813
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302814 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2815 if (err >= 0) {
2816 strlcpy(out->profile, value, sizeof(out->profile));
2817 ALOGV("updating stream profile with value '%s'", out->profile);
2818 lock_output_stream(out);
2819 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2820 &adev->streams_output_cfg_list,
2821 out->devices, out->flags, out->format,
2822 out->sample_rate, out->bit_width,
2823 out->channel_mask, out->profile,
2824 &out->app_type_cfg);
2825 pthread_mutex_unlock(&out->lock);
2826 }
2827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302829error:
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 return ret;
2832}
2833
2834static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2835{
2836 struct stream_out *out = (struct stream_out *)stream;
2837 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002838 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 char value[256];
2840 struct str_parms *reply = str_parms_create();
2841 size_t i, j;
2842 int ret;
2843 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002844
2845 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002846 if (reply) {
2847 str_parms_destroy(reply);
2848 }
2849 if (query) {
2850 str_parms_destroy(query);
2851 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002852 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2853 return NULL;
2854 }
2855
Eric Laurent994a6932013-07-17 11:51:42 -07002856 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2858 if (ret >= 0) {
2859 value[0] = '\0';
2860 i = 0;
2861 while (out->supported_channel_masks[i] != 0) {
2862 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2863 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2864 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002865 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002867 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 first = false;
2869 break;
2870 }
2871 }
2872 i++;
2873 }
2874 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2875 str = str_parms_to_str(reply);
2876 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002877 voice_extn_out_get_parameters(out, query, reply);
2878 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002879 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002880 free(str);
2881 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002882 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002884
Alexy Joseph62142aa2015-11-16 15:10:34 -08002885
2886 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2887 if (ret >= 0) {
2888 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302889 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2890 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002891 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302892 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002893 } else {
2894 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302895 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002896 }
2897 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002898 if (str)
2899 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002900 str = str_parms_to_str(reply);
2901 }
2902
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002903 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2904 if (ret >= 0) {
2905 value[0] = '\0';
2906 i = 0;
2907 first = true;
2908 while (out->supported_formats[i] != 0) {
2909 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2910 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2911 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002912 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913 }
2914 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2915 first = false;
2916 break;
2917 }
2918 }
2919 i++;
2920 }
2921 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002922 if (str)
2923 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002924 str = str_parms_to_str(reply);
2925 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002926
2927 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2928 if (ret >= 0) {
2929 value[0] = '\0';
2930 i = 0;
2931 first = true;
2932 while (out->supported_sample_rates[i] != 0) {
2933 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2934 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2935 if (!first) {
2936 strlcat(value, "|", sizeof(value));
2937 }
2938 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2939 first = false;
2940 break;
2941 }
2942 }
2943 i++;
2944 }
2945 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2946 if (str)
2947 free(str);
2948 str = str_parms_to_str(reply);
2949 }
2950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 str_parms_destroy(query);
2952 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002953 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 return str;
2955}
2956
2957static uint32_t out_get_latency(const struct audio_stream_out *stream)
2958{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002959 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002961 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962
Alexy Josephaa54c872014-12-03 02:46:47 -08002963 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002964 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002965 } else if (out->realtime) {
2966 // since the buffer won't be filled up faster than realtime,
2967 // return a smaller number
2968 if (out->config.rate)
2969 period_ms = (out->af_period_multiplier * out->config.period_size *
2970 1000) / (out->config.rate);
2971 else
2972 period_ms = 0;
2973 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002974 } else {
2975 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002976 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002977 }
2978
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002979 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2980 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2981 latency += audio_extn_a2dp_get_encoder_latency();
2982
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302983 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002984 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985}
2986
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302987static float AmpToDb(float amplification)
2988{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302989 float db = DSD_VOLUME_MIN_DB;
2990 if (amplification > 0) {
2991 db = 20 * log10(amplification);
2992 if(db < DSD_VOLUME_MIN_DB)
2993 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302994 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302995 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302996}
2997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998static int out_set_volume(struct audio_stream_out *stream, float left,
2999 float right)
3000{
Eric Laurenta9024de2013-04-04 09:19:12 -07003001 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003002 int volume[2];
3003
Eric Laurenta9024de2013-04-04 09:19:12 -07003004 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3005 /* only take left channel into account: the API is for stereo anyway */
3006 out->muted = (left == 0.0f);
3007 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003008 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303009 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003010 /*
3011 * Set mute or umute on HDMI passthrough stream.
3012 * Only take left channel into account.
3013 * Mute is 0 and unmute 1
3014 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303015 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303016 } else if (out->format == AUDIO_FORMAT_DSD){
3017 char mixer_ctl_name[128] = "DSD Volume";
3018 struct audio_device *adev = out->dev;
3019 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3020
3021 if (!ctl) {
3022 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3023 __func__, mixer_ctl_name);
3024 return -EINVAL;
3025 }
3026 volume[0] = (int)(AmpToDb(left));
3027 volume[1] = (int)(AmpToDb(right));
3028 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3029 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003030 } else {
3031 char mixer_ctl_name[128];
3032 struct audio_device *adev = out->dev;
3033 struct mixer_ctl *ctl;
3034 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003035 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003037 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3038 "Compress Playback %d Volume", pcm_device_id);
3039 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3040 if (!ctl) {
3041 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3042 __func__, mixer_ctl_name);
3043 return -EINVAL;
3044 }
3045 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3046 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3047 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3048 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003050 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 return -ENOSYS;
3053}
3054
3055static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3056 size_t bytes)
3057{
3058 struct stream_out *out = (struct stream_out *)stream;
3059 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303060 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003061 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003063 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303064
Naresh Tanniru80659832014-06-04 18:17:56 +05303065 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003066
Dhananjay Kumarac341582017-02-23 23:42:25 +05303067 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303068 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303069 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3070 pthread_mutex_unlock(&out->lock);
3071 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303072 } else {
3073 /* increase written size during SSR to avoid mismatch
3074 * with the written frames count in AF
3075 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003076 // bytes per frame
3077 size_t bpf = audio_bytes_per_sample(out->format) *
3078 audio_channel_count_from_out_mask(out->channel_mask);
3079 if (bpf != 0)
3080 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303081 ALOGD(" %s: sound card is not active/SSR state", __func__);
3082 ret= -EIO;
3083 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303084 }
3085 }
3086
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303087 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303088 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3089 if (audio_bytes_per_sample(out->format) != 0)
3090 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3091 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303092 goto exit;
3093 }
3094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003096 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003097 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003098 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3099 ret = voice_extn_compress_voip_start_output_stream(out);
3100 else
3101 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003102 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003105 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 goto exit;
3107 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003108
3109 if (last_known_cal_step != -1) {
3110 ALOGD("%s: retry previous failed cal level set", __func__);
3111 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
Ashish Jain81eb2a82015-05-13 10:52:34 +05303115 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003116 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303117 adev->is_channel_status_set = true;
3118 }
3119
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003120 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003121 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003122 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003123 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003124 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3125 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303126 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3127 ALOGD("copl(%p):send next track params in gapless", out);
3128 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3129 out->send_next_track_params = false;
3130 out->is_compr_metadata_avail = false;
3131 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003132 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303133 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303134 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003135
Ashish Jain83a6cc22016-06-28 14:34:17 +05303136 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303137 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303138 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303139 pthread_mutex_unlock(&out->lock);
3140 return -EINVAL;
3141 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303142 audio_format_t dst_format = out->hal_op_format;
3143 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303144
3145 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3146 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3147
Ashish Jain83a6cc22016-06-28 14:34:17 +05303148 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303149 dst_format,
3150 buffer,
3151 src_format,
3152 frames);
3153
Ashish Jain83a6cc22016-06-28 14:34:17 +05303154 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303155 bytes_to_write);
3156
3157 /*Convert written bytes in audio flinger format*/
3158 if (ret > 0)
3159 ret = ((ret * format_to_bitwidth_table[out->format]) /
3160 format_to_bitwidth_table[dst_format]);
3161 }
3162 } else
3163 ret = compress_write(out->compr, buffer, bytes);
3164
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303165 if (ret < 0)
3166 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303167 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303168 /*msg to cb thread only if non blocking write is enabled*/
3169 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303170 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303172 } else if (-ENETRESET == ret) {
3173 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3174 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3175 pthread_mutex_unlock(&out->lock);
3176 out_standby(&out->stream.common);
3177 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178 }
Ashish Jain5106d362016-05-11 19:23:33 +05303179 if ( ret == (ssize_t)bytes && !out->non_blocking)
3180 out->written += bytes;
3181
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303182 /* Call compr start only when non-zero bytes of data is there to be rendered */
3183 if (!out->playback_started && ret > 0) {
3184 int status = compress_start(out->compr);
3185 if (status < 0) {
3186 ret = status;
3187 ALOGE("%s: compr start failed with err %d", __func__, errno);
3188 goto exit;
3189 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003190 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 out->playback_started = 1;
3192 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003193
3194 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3195 popcount(out->channel_mask),
3196 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 }
3198 pthread_mutex_unlock(&out->lock);
3199 return ret;
3200 } else {
3201 if (out->pcm) {
3202 if (out->muted)
3203 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003204
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303205 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003206
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003207 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003208
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003209 if (out->config.rate)
3210 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3211 out->config.rate;
3212
3213 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3214
3215 request_out_focus(out, ns);
3216
3217 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003218 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003219 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303220 out->convert_buffer != NULL) {
3221
3222 memcpy_by_audio_format(out->convert_buffer,
3223 out->hal_op_format,
3224 buffer,
3225 out->hal_ip_format,
3226 out->config.period_size * out->config.channels);
3227
3228 ret = pcm_write(out->pcm, out->convert_buffer,
3229 (out->config.period_size *
3230 out->config.channels *
3231 format_to_bitwidth_table[out->hal_op_format]));
3232 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003233 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303234 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003235
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003236 release_out_focus(out);
3237
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303238 if (ret < 0)
3239 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303240 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3241 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3242 else
3243 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 }
3246
3247exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303248 /* ToDo: There may be a corner case when SSR happens back to back during
3249 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303250 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303251 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303252 }
3253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 pthread_mutex_unlock(&out->lock);
3255
3256 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003257 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003258 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303259 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303260 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303261 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303262 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303263 out->standby = true;
3264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303266 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3267 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3268 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 }
3270 return bytes;
3271}
3272
3273static int out_get_render_position(const struct audio_stream_out *stream,
3274 uint32_t *dsp_frames)
3275{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003276 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303277 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003278
3279 if (dsp_frames == NULL)
3280 return -EINVAL;
3281
3282 *dsp_frames = 0;
3283 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003284 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303285
3286 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3287 * this operation and adev_close_output_stream(where out gets reset).
3288 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303289 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303290 *dsp_frames = get_actual_pcm_frames_rendered(out);
3291 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3292 return 0;
3293 }
3294
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003295 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303296 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303297 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003298 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303299 if (ret < 0)
3300 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003301 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303302 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003303 }
3304 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303305 if (-ENETRESET == ret) {
3306 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3307 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3308 return -EINVAL;
3309 } else if(ret < 0) {
3310 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3311 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303312 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3313 /*
3314 * Handle corner case where compress session is closed during SSR
3315 * and timestamp is queried
3316 */
3317 ALOGE(" ERROR: sound card not active, return error");
3318 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303319 } else {
3320 return 0;
3321 }
Zhou Song32a556e2015-05-05 10:46:56 +08003322 } else if (audio_is_linear_pcm(out->format)) {
3323 *dsp_frames = out->written;
3324 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003325 } else
3326 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327}
3328
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003329static int out_add_audio_effect(const struct audio_stream *stream __unused,
3330 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331{
3332 return 0;
3333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3336 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return 0;
3339}
3340
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003341static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3342 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 return -EINVAL;
3345}
3346
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003347static int out_get_presentation_position(const struct audio_stream_out *stream,
3348 uint64_t *frames, struct timespec *timestamp)
3349{
3350 struct stream_out *out = (struct stream_out *)stream;
3351 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003352 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003353
Ashish Jain5106d362016-05-11 19:23:33 +05303354 /* below piece of code is not guarded against any lock because audioFliner serializes
3355 * this operation and adev_close_output_stream( where out gets reset).
3356 */
3357 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303358 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303359 *frames = get_actual_pcm_frames_rendered(out);
3360 /* this is the best we can do */
3361 clock_gettime(CLOCK_MONOTONIC, timestamp);
3362 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3363 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3364 return 0;
3365 }
3366
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003367 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003368
Ashish Jain5106d362016-05-11 19:23:33 +05303369 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3370 ret = compress_get_tstamp(out->compr, &dsp_frames,
3371 &out->sample_rate);
3372 ALOGVV("%s rendered frames %ld sample_rate %d",
3373 __func__, dsp_frames, out->sample_rate);
3374 *frames = dsp_frames;
3375 if (ret < 0)
3376 ret = -errno;
3377 if (-ENETRESET == ret) {
3378 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3379 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3380 ret = -EINVAL;
3381 } else
3382 ret = 0;
3383 /* this is the best we can do */
3384 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003385 } else {
3386 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003387 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003388 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3389 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003390 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003391 // This adjustment accounts for buffering after app processor.
3392 // It is based on estimated DSP latency per use case, rather than exact.
3393 signed_frames -=
3394 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3395
Eric Laurent949a0892013-09-20 09:20:13 -07003396 // It would be unusual for this value to be negative, but check just in case ...
3397 if (signed_frames >= 0) {
3398 *frames = signed_frames;
3399 ret = 0;
3400 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003401 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303402 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3403 *frames = out->written;
3404 clock_gettime(CLOCK_MONOTONIC, timestamp);
3405 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003406 }
3407 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003408 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003409 return ret;
3410}
3411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412static int out_set_callback(struct audio_stream_out *stream,
3413 stream_callback_t callback, void *cookie)
3414{
3415 struct stream_out *out = (struct stream_out *)stream;
3416
3417 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003418 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003419 out->offload_callback = callback;
3420 out->offload_cookie = cookie;
3421 pthread_mutex_unlock(&out->lock);
3422 return 0;
3423}
3424
3425static int out_pause(struct audio_stream_out* stream)
3426{
3427 struct stream_out *out = (struct stream_out *)stream;
3428 int status = -ENOSYS;
3429 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003430 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003431 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003432 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303434 struct audio_device *adev = out->dev;
3435 int snd_scard_state = get_snd_card_state(adev);
3436
3437 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3438 status = compress_pause(out->compr);
3439
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003441
Mingming Yin21854652016-04-13 11:54:02 -07003442 if (audio_extn_passthru_is_active()) {
3443 ALOGV("offload use case, pause passthru");
3444 audio_extn_passthru_on_pause(out);
3445 }
3446
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303447 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003448 audio_extn_dts_notify_playback_state(out->usecase, 0,
3449 out->sample_rate, popcount(out->channel_mask),
3450 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003451 }
3452 pthread_mutex_unlock(&out->lock);
3453 }
3454 return status;
3455}
3456
3457static int out_resume(struct audio_stream_out* stream)
3458{
3459 struct stream_out *out = (struct stream_out *)stream;
3460 int status = -ENOSYS;
3461 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003462 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003463 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003464 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003466 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303467 struct audio_device *adev = out->dev;
3468 int snd_scard_state = get_snd_card_state(adev);
3469
Mingming Yin21854652016-04-13 11:54:02 -07003470 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3471 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3472 pthread_mutex_lock(&out->dev->lock);
3473 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003474 pthread_mutex_unlock(&out->dev->lock);
3475 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303476 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003477 }
3478 if (!status) {
3479 out->offload_state = OFFLOAD_STATE_PLAYING;
3480 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303481 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003482 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3483 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 }
3485 pthread_mutex_unlock(&out->lock);
3486 }
3487 return status;
3488}
3489
3490static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3491{
3492 struct stream_out *out = (struct stream_out *)stream;
3493 int status = -ENOSYS;
3494 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003495 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003496 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3498 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3499 else
3500 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3501 pthread_mutex_unlock(&out->lock);
3502 }
3503 return status;
3504}
3505
3506static int out_flush(struct audio_stream_out* stream)
3507{
3508 struct stream_out *out = (struct stream_out *)stream;
3509 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003510 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003511 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003512 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003513 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3514 stop_compressed_output_l(out);
3515 out->written = 0;
3516 } else {
3517 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3518 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003520 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003521 return 0;
3522 }
3523 return -ENOSYS;
3524}
3525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526/** audio_stream_in implementation **/
3527static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3528{
3529 struct stream_in *in = (struct stream_in *)stream;
3530
3531 return in->config.rate;
3532}
3533
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003534static int in_set_sample_rate(struct audio_stream *stream __unused,
3535 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536{
3537 return -ENOSYS;
3538}
3539
3540static size_t in_get_buffer_size(const struct audio_stream *stream)
3541{
3542 struct stream_in *in = (struct stream_in *)stream;
3543
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003544 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3545 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003546 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3547 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303548 else if(audio_extn_cin_attached_usecase(in->usecase))
3549 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003550
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003551 return in->config.period_size * in->af_period_multiplier *
3552 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553}
3554
3555static uint32_t in_get_channels(const struct audio_stream *stream)
3556{
3557 struct stream_in *in = (struct stream_in *)stream;
3558
3559 return in->channel_mask;
3560}
3561
3562static audio_format_t in_get_format(const struct audio_stream *stream)
3563{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003564 struct stream_in *in = (struct stream_in *)stream;
3565
3566 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567}
3568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003569static int in_set_format(struct audio_stream *stream __unused,
3570 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571{
3572 return -ENOSYS;
3573}
3574
3575static int in_standby(struct audio_stream *stream)
3576{
3577 struct stream_in *in = (struct stream_in *)stream;
3578 struct audio_device *adev = in->dev;
3579 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303580 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3581 stream, in->usecase, use_case_table[in->usecase]);
3582
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003583 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003584 if (!in->standby && in->is_st_session) {
3585 ALOGD("%s: sound trigger pcm stop lab", __func__);
3586 audio_extn_sound_trigger_stop_lab(in);
3587 in->standby = 1;
3588 }
3589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003591 if (adev->adm_deregister_stream)
3592 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3593
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003594 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003596 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3597 voice_extn_compress_voip_close_input_stream(stream);
3598 ALOGD("VOIP input entered standby");
3599 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303600 if (audio_extn_cin_attached_usecase(in->usecase))
3601 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003602 if (in->pcm) {
3603 pcm_close(in->pcm);
3604 in->pcm = NULL;
3605 }
3606 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003607 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003608 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 }
3610 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003611 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 return status;
3613}
3614
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003615static int in_dump(const struct audio_stream *stream __unused,
3616 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617{
3618 return 0;
3619}
3620
3621static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3622{
3623 struct stream_in *in = (struct stream_in *)stream;
3624 struct audio_device *adev = in->dev;
3625 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003627 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303629 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 parms = str_parms_create_str(kvpairs);
3631
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303632 if (!parms)
3633 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003634 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003635 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003636
3637 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3638 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 val = atoi(value);
3640 /* no audio source uses val == 0 */
3641 if ((in->source != val) && (val != 0)) {
3642 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003643 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3644 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3645 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003646 (in->config.rate == 8000 || in->config.rate == 16000 ||
3647 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003648 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003649 err = voice_extn_compress_voip_open_input_stream(in);
3650 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003651 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003652 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003653 }
3654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 }
3656 }
3657
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003658 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3659 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003661 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 in->device = val;
3663 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003664 if (!in->standby && !in->is_st_session) {
3665 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003666 if (adev->adm_on_routing_change)
3667 adev->adm_on_routing_change(adev->adm_data,
3668 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003669 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 }
3672 }
3673
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303674 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3675 if (err >= 0) {
3676 strlcpy(in->profile, value, sizeof(in->profile));
3677 ALOGV("updating stream profile with value '%s'", in->profile);
3678 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3679 &adev->streams_input_cfg_list,
3680 in->device, in->flags, in->format,
3681 in->sample_rate, in->bit_width,
3682 in->profile, &in->app_type_cfg);
3683 }
3684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003686 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687
3688 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303689error:
Eric Laurent994a6932013-07-17 11:51:42 -07003690 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 return ret;
3692}
3693
3694static char* in_get_parameters(const struct audio_stream *stream,
3695 const char *keys)
3696{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003697 struct stream_in *in = (struct stream_in *)stream;
3698 struct str_parms *query = str_parms_create_str(keys);
3699 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003700 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003701
3702 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003703 if (reply) {
3704 str_parms_destroy(reply);
3705 }
3706 if (query) {
3707 str_parms_destroy(query);
3708 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003709 ALOGE("in_get_parameters: failed to create query or reply");
3710 return NULL;
3711 }
3712
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003713 ALOGV("%s: enter: keys - %s", __func__, keys);
3714
3715 voice_extn_in_get_parameters(in, query, reply);
3716
3717 str = str_parms_to_str(reply);
3718 str_parms_destroy(query);
3719 str_parms_destroy(reply);
3720
3721 ALOGV("%s: exit: returns - %s", __func__, str);
3722 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723}
3724
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003725static int in_set_gain(struct audio_stream_in *stream __unused,
3726 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727{
3728 return 0;
3729}
3730
3731static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3732 size_t bytes)
3733{
3734 struct stream_in *in = (struct stream_in *)stream;
3735 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303736 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303737 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303738 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003740 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303741
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003742 if (in->is_st_session) {
3743 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3744 /* Read from sound trigger HAL */
3745 audio_extn_sound_trigger_read(in, buffer, bytes);
3746 pthread_mutex_unlock(&in->lock);
3747 return bytes;
3748 }
3749
Ashish Jainbbce4322016-02-16 13:25:27 +05303750 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003751 ALOGD(" %s: sound card is not active/SSR state", __func__);
3752 ret= -EIO;;
3753 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303754 }
3755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003757 pthread_mutex_lock(&adev->lock);
3758 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3759 ret = voice_extn_compress_voip_start_input_stream(in);
3760 else
3761 ret = start_input_stream(in);
3762 pthread_mutex_unlock(&adev->lock);
3763 if (ret != 0) {
3764 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 }
3766 in->standby = 0;
3767 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003769 // what's the duration requested by the client?
3770 long ns = 0;
3771
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303772 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003773 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3774 in->config.rate;
3775
3776 request_in_focus(in, ns);
3777 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003778
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303779 if (audio_extn_cin_attached_usecase(in->usecase)) {
3780 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3781 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303782 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003783 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303784 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003785 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003786 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003787 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303788 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003789 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303790 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3791 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3792 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3793 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303794 ret = -EINVAL;
3795 goto exit;
3796 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303797 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303798 ret = -errno;
3799 }
3800 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303801 /* bytes read is always set to bytes for non compress usecases */
3802 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 }
3804
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003805 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 /*
3808 * Instead of writing zeroes here, we could trust the hardware
3809 * to always provide zeroes when muted.
3810 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303811 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3812 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 memset(buffer, 0, bytes);
3814
3815exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303816 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303817 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003818 if (-ENETRESET == ret)
3819 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 pthread_mutex_unlock(&in->lock);
3822
3823 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303824 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303825 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303826 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303827 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303828 in->standby = true;
3829 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303830 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3831 bytes_read = bytes;
3832 memset(buffer, 0, bytes);
3833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003835 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303836 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303837 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303839 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840}
3841
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003842static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843{
3844 return 0;
3845}
3846
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003847static int add_remove_audio_effect(const struct audio_stream *stream,
3848 effect_handle_t effect,
3849 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003851 struct stream_in *in = (struct stream_in *)stream;
3852 int status = 0;
3853 effect_descriptor_t desc;
3854
3855 status = (*effect)->get_descriptor(effect, &desc);
3856 if (status != 0)
3857 return status;
3858
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003859 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003860 pthread_mutex_lock(&in->dev->lock);
3861 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3862 in->enable_aec != enable &&
3863 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3864 in->enable_aec = enable;
3865 if (!in->standby)
3866 select_devices(in->dev, in->usecase);
3867 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003868 if (in->enable_ns != enable &&
3869 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3870 in->enable_ns = enable;
3871 if (!in->standby)
3872 select_devices(in->dev, in->usecase);
3873 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003874 pthread_mutex_unlock(&in->dev->lock);
3875 pthread_mutex_unlock(&in->lock);
3876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 return 0;
3878}
3879
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003880static int in_add_audio_effect(const struct audio_stream *stream,
3881 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882{
Eric Laurent994a6932013-07-17 11:51:42 -07003883 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003884 return add_remove_audio_effect(stream, effect, true);
3885}
3886
3887static int in_remove_audio_effect(const struct audio_stream *stream,
3888 effect_handle_t effect)
3889{
Eric Laurent994a6932013-07-17 11:51:42 -07003890 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003891 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892}
3893
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303894int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895 audio_io_handle_t handle,
3896 audio_devices_t devices,
3897 audio_output_flags_t flags,
3898 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003899 struct audio_stream_out **stream_out,
3900 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901{
3902 struct audio_device *adev = (struct audio_device *)dev;
3903 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303904 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003905 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303908
3909 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3910 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003911 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303912 return -EINVAL;
3913 }
3914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3916
Mingming Yin3a941d42016-02-17 18:08:05 -08003917 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3918 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303919 devices, flags, &out->stream);
3920
3921
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003922 if (!out) {
3923 return -ENOMEM;
3924 }
3925
Haynes Mathew George204045b2015-02-25 20:32:03 -08003926 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003927 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003928 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 if (devices == AUDIO_DEVICE_NONE)
3931 devices = AUDIO_DEVICE_OUT_SPEAKER;
3932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 out->flags = flags;
3934 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003935 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003936 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003937 out->sample_rate = config->sample_rate;
3938 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3939 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003940 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003941 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003942 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303943 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944
Mingming Yin3a941d42016-02-17 18:08:05 -08003945 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3946 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3947 pthread_mutex_lock(&adev->lock);
3948 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3949 ret = read_hdmi_sink_caps(out);
3950 pthread_mutex_unlock(&adev->lock);
3951 if (ret != 0) {
3952 if (ret == -ENOSYS) {
3953 /* ignore and go with default */
3954 ret = 0;
3955 } else {
3956 ALOGE("error reading hdmi sink caps");
3957 goto error_open;
3958 }
3959 }
3960 }
3961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303963 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003964 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003965 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003966 ret = voice_extn_compress_voip_open_output_stream(out);
3967 if (ret != 0) {
3968 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3969 __func__, ret);
3970 goto error_open;
3971 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003972 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05303973 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3976 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3977 ALOGE("%s: Unsupported Offload information", __func__);
3978 ret = -EINVAL;
3979 goto error_open;
3980 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003981
Mingming Yin3a941d42016-02-17 18:08:05 -08003982 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003983 if(config->offload_info.format == 0)
3984 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003985 if (config->offload_info.sample_rate == 0)
3986 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003987 }
3988
Mingming Yin90310102013-11-13 16:57:00 -08003989 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303990 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003991 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003992 ret = -EINVAL;
3993 goto error_open;
3994 }
3995
3996 out->compr_config.codec = (struct snd_codec *)
3997 calloc(1, sizeof(struct snd_codec));
3998
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003999 if (!out->compr_config.codec) {
4000 ret = -ENOMEM;
4001 goto error_open;
4002 }
4003
Dhananjay Kumarac341582017-02-23 23:42:25 +05304004 out->stream.pause = out_pause;
4005 out->stream.resume = out_resume;
4006 out->stream.flush = out_flush;
4007 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004008 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004009 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304010 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004011 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304012 } else {
4013 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4014 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004015 }
vivek mehta446c3962015-09-14 10:57:35 -07004016
4017 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004018 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4019 config->format == 0 && config->sample_rate == 0 &&
4020 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004021 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004022 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4023 } else {
4024 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4025 ret = -EEXIST;
4026 goto error_open;
4027 }
vivek mehta446c3962015-09-14 10:57:35 -07004028 }
4029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004030 if (config->offload_info.channel_mask)
4031 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004032 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004033 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004034 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004035 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304036 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004037 ret = -EINVAL;
4038 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004039 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004040
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004041 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004042 out->sample_rate = config->offload_info.sample_rate;
4043
Mingming Yin3ee55c62014-08-04 14:23:35 -07004044 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004045
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304046 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4047 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4048 audio_extn_dolby_send_ddp_endp_params(adev);
4049 audio_extn_dolby_set_dmid(adev);
4050 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004051
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004052 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004053 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004054 out->compr_config.codec->bit_rate =
4055 config->offload_info.bit_rate;
4056 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304057 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004058 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304059 /* Update bit width only for non passthrough usecases.
4060 * For passthrough usecases, the output will always be opened @16 bit
4061 */
4062 if (!audio_extn_passthru_is_passthrough_stream(out))
4063 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004064 /*TODO: Do we need to change it for passthrough */
4065 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066
Manish Dewangana6fc5442015-08-24 20:30:31 +05304067 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4068 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304069 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304070 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304071 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304073
4074 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4075 AUDIO_FORMAT_PCM) {
4076
4077 /*Based on platform support, configure appropriate alsa format for corresponding
4078 *hal input format.
4079 */
4080 out->compr_config.codec->format = hal_format_to_alsa(
4081 config->offload_info.format);
4082
Ashish Jain83a6cc22016-06-28 14:34:17 +05304083 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304084 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304085 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304086
Dhananjay Kumarac341582017-02-23 23:42:25 +05304087 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304088 *hal input format and alsa format might differ based on platform support.
4089 */
4090 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304091 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304092
4093 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4094
4095 /* Check if alsa session is configured with the same format as HAL input format,
4096 * if not then derive correct fragment size needed to accomodate the
4097 * conversion of HAL input format to alsa format.
4098 */
4099 audio_extn_utils_update_direct_pcm_fragment_size(out);
4100
4101 /*if hal input and output fragment size is different this indicates HAL input format is
4102 *not same as the alsa format
4103 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304104 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304105 /*Allocate a buffer to convert input data to the alsa configured format.
4106 *size of convert buffer is equal to the size required to hold one fragment size
4107 *worth of pcm data, this is because flinger does not write more than fragment_size
4108 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304109 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4110 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304111 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4112 ret = -ENOMEM;
4113 goto error_open;
4114 }
4115 }
4116 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4117 out->compr_config.fragment_size =
4118 audio_extn_passthru_get_buffer_size(&config->offload_info);
4119 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4120 } else {
4121 out->compr_config.fragment_size =
4122 platform_get_compress_offload_buffer_size(&config->offload_info);
4123 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4124 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004125
Amit Shekhar6f461b12014-08-01 14:52:58 -07004126 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304127 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004128
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304129 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4130 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4131 }
4132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004133 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4134 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004135
Alexy Josephaa54c872014-12-03 02:46:47 -08004136
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004137 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304138 out->send_next_track_params = false;
4139 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004140 out->offload_state = OFFLOAD_STATE_IDLE;
4141 out->playback_started = 0;
4142
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004143 audio_extn_dts_create_state_notifier_node(out->usecase);
4144
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004145 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4146 __func__, config->offload_info.version,
4147 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304148
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304149 /* Check if DSD audio format is supported in codec
4150 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304151 */
4152
4153 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304154 (!platform_check_codec_dsd_support(adev->platform) ||
4155 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304156 ret = -EINVAL;
4157 goto error_open;
4158 }
4159
Ashish Jain5106d362016-05-11 19:23:33 +05304160 /* Disable gapless if any of the following is true
4161 * passthrough playback
4162 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304163 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304164 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304165 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304166 (config->format == AUDIO_FORMAT_DSD) ||
4167 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304168 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304169 check_and_set_gapless_mode(adev, false);
4170 } else
4171 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004172
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304173 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004174 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4175 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304176 if (config->format == AUDIO_FORMAT_DSD) {
4177 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4178 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4179 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004180
4181 create_offload_callback_thread(out);
4182
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004183 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304184 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004185 if (ret != 0) {
4186 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4187 __func__, ret);
4188 goto error_open;
4189 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004190 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4191 if (config->sample_rate == 0)
4192 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4193 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4194 config->sample_rate != 8000) {
4195 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4196 ret = -EINVAL;
4197 goto error_open;
4198 }
4199 out->sample_rate = config->sample_rate;
4200 out->config.rate = config->sample_rate;
4201 if (config->format == AUDIO_FORMAT_DEFAULT)
4202 config->format = AUDIO_FORMAT_PCM_16_BIT;
4203 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4204 config->format = AUDIO_FORMAT_PCM_16_BIT;
4205 ret = -EINVAL;
4206 goto error_open;
4207 }
4208 out->format = config->format;
4209 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4210 out->config = pcm_config_afe_proxy_playback;
4211 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004212 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304213 unsigned int channels = 0;
4214 /*Update config params to default if not set by the caller*/
4215 if (config->sample_rate == 0)
4216 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4217 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4218 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4219 if (config->format == AUDIO_FORMAT_DEFAULT)
4220 config->format = AUDIO_FORMAT_PCM_16_BIT;
4221
4222 channels = audio_channel_count_from_out_mask(out->channel_mask);
4223
Ashish Jain83a6cc22016-06-28 14:34:17 +05304224 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4225 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004226 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4227 out->flags);
4228 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304229 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4230 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4231 out->config = pcm_config_low_latency;
4232 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4233 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4234 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304235 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4236 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4237 if (out->config.period_size <= 0) {
4238 ALOGE("Invalid configuration period size is not valid");
4239 ret = -EINVAL;
4240 goto error_open;
4241 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304242 } else {
4243 /* primary path is the default path selected if no other outputs are available/suitable */
4244 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4245 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4246 }
4247 out->hal_ip_format = format = out->format;
4248 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4249 out->hal_op_format = pcm_format_to_hal(out->config.format);
4250 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4251 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004252 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304253 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304254 if (out->hal_ip_format != out->hal_op_format) {
4255 uint32_t buffer_size = out->config.period_size *
4256 format_to_bitwidth_table[out->hal_op_format] *
4257 out->config.channels;
4258 out->convert_buffer = calloc(1, buffer_size);
4259 if (out->convert_buffer == NULL){
4260 ALOGE("Allocation failed for convert buffer for size %d",
4261 out->compr_config.fragment_size);
4262 ret = -ENOMEM;
4263 goto error_open;
4264 }
4265 ALOGD("Convert buffer allocated of size %d", buffer_size);
4266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 }
4268
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004269 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4270 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304271
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004272 /* TODO remove this hardcoding and check why width is zero*/
4273 if (out->bit_width == 0)
4274 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304275 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004276 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304277 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304278 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304279 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004280 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4281 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4282 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004283 if(adev->primary_output == NULL)
4284 adev->primary_output = out;
4285 else {
4286 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004287 ret = -EEXIST;
4288 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004289 }
4290 }
4291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 /* Check if this usecase is already existing */
4293 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004294 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4295 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004297 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004298 ret = -EEXIST;
4299 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 pthread_mutex_unlock(&adev->lock);
4303
4304 out->stream.common.get_sample_rate = out_get_sample_rate;
4305 out->stream.common.set_sample_rate = out_set_sample_rate;
4306 out->stream.common.get_buffer_size = out_get_buffer_size;
4307 out->stream.common.get_channels = out_get_channels;
4308 out->stream.common.get_format = out_get_format;
4309 out->stream.common.set_format = out_set_format;
4310 out->stream.common.standby = out_standby;
4311 out->stream.common.dump = out_dump;
4312 out->stream.common.set_parameters = out_set_parameters;
4313 out->stream.common.get_parameters = out_get_parameters;
4314 out->stream.common.add_audio_effect = out_add_audio_effect;
4315 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4316 out->stream.get_latency = out_get_latency;
4317 out->stream.set_volume = out_set_volume;
4318 out->stream.write = out_write;
4319 out->stream.get_render_position = out_get_render_position;
4320 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004321 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004323 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004325 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004326 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327
4328 config->format = out->stream.common.get_format(&out->stream.common);
4329 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4330 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4331
4332 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304333 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004334 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004335
4336 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4337 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4338 popcount(out->channel_mask), out->playback_started);
4339
Eric Laurent994a6932013-07-17 11:51:42 -07004340 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004342
4343error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304344 if (out->convert_buffer)
4345 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004346 free(out);
4347 *stream_out = NULL;
4348 ALOGD("%s: exit: ret %d", __func__, ret);
4349 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350}
4351
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304352void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 struct audio_stream_out *stream)
4354{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004355 struct stream_out *out = (struct stream_out *)stream;
4356 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004357 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004358
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304359 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4360
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004361 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304362 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004363 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304364 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004365 if(ret != 0)
4366 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4367 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004368 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004369 out_standby(&stream->common);
4370
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004371 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004372 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004373 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004374 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004375 if (out->compr_config.codec != NULL)
4376 free(out->compr_config.codec);
4377 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004378
Ashish Jain83a6cc22016-06-28 14:34:17 +05304379 if (out->convert_buffer != NULL) {
4380 free(out->convert_buffer);
4381 out->convert_buffer = NULL;
4382 }
4383
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004384 if (adev->voice_tx_output == out)
4385 adev->voice_tx_output = NULL;
4386
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304387 if (adev->primary_output == out)
4388 adev->primary_output = NULL;
4389
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004390 pthread_cond_destroy(&out->cond);
4391 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004393 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394}
4395
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004396static void close_compress_sessions(struct audio_device *adev)
4397{
Mingming Yin7b762e72015-03-04 13:47:32 -08004398 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304399 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004400 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004401 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304402
4403 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004404 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304405 if (is_offload_usecase(usecase->id)) {
4406 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004407 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4408 out = usecase->stream.out;
4409 pthread_mutex_unlock(&adev->lock);
4410 out_standby(&out->stream.common);
4411 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004412 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004413 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304414 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004415 }
4416 pthread_mutex_unlock(&adev->lock);
4417}
4418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4420{
4421 struct audio_device *adev = (struct audio_device *)dev;
4422 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004424 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004425 int ret;
4426 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004428 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304431 if (!parms)
4432 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004433 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4434 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304435 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304436 if (strstr(snd_card_status, "OFFLINE")) {
4437 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304438 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004439 //close compress sessions on OFFLINE status
4440 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304441 } else if (strstr(snd_card_status, "ONLINE")) {
4442 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304443 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004444 //send dts hpx license if enabled
4445 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304446 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304447 }
4448
4449 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004450 status = voice_set_parameters(adev, parms);
4451 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004452 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004454 status = platform_set_parameters(adev->platform, parms);
4455 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004456 goto done;
4457
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004458 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4459 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004460 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4462 adev->bluetooth_nrec = true;
4463 else
4464 adev->bluetooth_nrec = false;
4465 }
4466
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004467 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4468 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4470 adev->screen_off = false;
4471 else
4472 adev->screen_off = true;
4473 }
4474
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004475 ret = str_parms_get_int(parms, "rotation", &val);
4476 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004477 bool reverse_speakers = false;
4478 switch(val) {
4479 // FIXME: note that the code below assumes that the speakers are in the correct placement
4480 // relative to the user when the device is rotated 90deg from its default rotation. This
4481 // assumption is device-specific, not platform-specific like this code.
4482 case 270:
4483 reverse_speakers = true;
4484 break;
4485 case 0:
4486 case 90:
4487 case 180:
4488 break;
4489 default:
4490 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004491 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004492 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004493 if (status == 0) {
4494 if (adev->speaker_lr_swap != reverse_speakers) {
4495 adev->speaker_lr_swap = reverse_speakers;
4496 // only update the selected device if there is active pcm playback
4497 struct audio_usecase *usecase;
4498 struct listnode *node;
4499 list_for_each(node, &adev->usecase_list) {
4500 usecase = node_to_item(node, struct audio_usecase, list);
4501 if (usecase->type == PCM_PLAYBACK) {
4502 select_devices(adev, usecase->id);
4503 break;
4504 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004505 }
4506 }
4507 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004508 }
4509
Mingming Yin514a8bc2014-07-29 15:22:21 -07004510 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4511 if (ret >= 0) {
4512 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4513 adev->bt_wb_speech_enabled = true;
4514 else
4515 adev->bt_wb_speech_enabled = false;
4516 }
4517
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004518 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4519 if (ret >= 0) {
4520 val = atoi(value);
4521 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004522 ALOGV("cache new ext disp type and edid");
4523 ret = platform_get_ext_disp_type(adev->platform);
4524 if (ret < 0) {
4525 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004526 status = ret;
4527 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004528 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004529 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004530 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004531 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004532 /*
4533 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4534 * Per AudioPolicyManager, USB device is higher priority than WFD.
4535 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4536 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4537 * starting voice call on USB
4538 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004539 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4540 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004541 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4542 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004543 }
vivek mehta344576a2016-04-12 18:56:03 -07004544 ALOGV("detected USB connect .. disable proxy");
4545 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004546 }
4547 }
4548
4549 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4550 if (ret >= 0) {
4551 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004552 /*
4553 * The HDMI / Displayport disconnect handling has been moved to
4554 * audio extension to ensure that its parameters are not
4555 * invalidated prior to updating sysfs of the disconnect event
4556 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4557 */
4558 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004559 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004560 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4561 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304562 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4563 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004564 }
vivek mehta344576a2016-04-12 18:56:03 -07004565 ALOGV("detected USB disconnect .. enable proxy");
4566 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004567 }
4568 }
4569
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304570 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4571 if (ret >= 0) {
4572 struct audio_usecase *usecase;
4573 struct listnode *node;
4574 list_for_each(node, &adev->usecase_list) {
4575 usecase = node_to_item(node, struct audio_usecase, list);
4576 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004577 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304578 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304579 lock_output_stream(usecase->stream.out);
4580 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304581 //force device switch to re configure encoder
4582 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304583 audio_extn_a2dp_set_handoff_mode(false);
4584 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304585 break;
4586 }
4587 }
4588 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004589
4590 //handle vr audio setparam
4591 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4592 value, sizeof(value));
4593 if (ret >= 0) {
4594 ALOGI("Setting vr mode to be %s", value);
4595 if (!strncmp(value, "true", 4)) {
4596 adev->vr_audio_mode_enabled = true;
4597 ALOGI("Setting vr mode to true");
4598 } else if (!strncmp(value, "false", 5)) {
4599 adev->vr_audio_mode_enabled = false;
4600 ALOGI("Setting vr mode to false");
4601 } else {
4602 ALOGI("wrong vr mode set");
4603 }
4604 }
4605
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304606 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004607done:
4608 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004609 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304610error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004611 ALOGV("%s: exit with code(%d)", __func__, status);
4612 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613}
4614
4615static char* adev_get_parameters(const struct audio_hw_device *dev,
4616 const char *keys)
4617{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004618 struct audio_device *adev = (struct audio_device *)dev;
4619 struct str_parms *reply = str_parms_create();
4620 struct str_parms *query = str_parms_create_str(keys);
4621 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304622 char value[256] = {0};
4623 int ret = 0;
4624
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004625 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004626 if (reply) {
4627 str_parms_destroy(reply);
4628 }
4629 if (query) {
4630 str_parms_destroy(query);
4631 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004632 ALOGE("adev_get_parameters: failed to create query or reply");
4633 return NULL;
4634 }
4635
Naresh Tannirud7205b62014-06-20 02:54:48 +05304636 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4637 sizeof(value));
4638 if (ret >=0) {
4639 int val = 1;
4640 pthread_mutex_lock(&adev->snd_card_status.lock);
4641 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4642 val = 0;
4643 pthread_mutex_unlock(&adev->snd_card_status.lock);
4644 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4645 goto exit;
4646 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004647 //handle vr audio getparam
4648
4649 ret = str_parms_get_str(query,
4650 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4651 value, sizeof(value));
4652
4653 if (ret >= 0) {
4654 bool vr_audio_enabled = false;
4655 pthread_mutex_lock(&adev->lock);
4656 vr_audio_enabled = adev->vr_audio_mode_enabled;
4657 pthread_mutex_unlock(&adev->lock);
4658
4659 ALOGI("getting vr mode to %d", vr_audio_enabled);
4660
4661 if (vr_audio_enabled) {
4662 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4663 "true");
4664 goto exit;
4665 } else {
4666 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4667 "false");
4668 goto exit;
4669 }
4670 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004671
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004672 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004673 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004674 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004675 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304676 pthread_mutex_unlock(&adev->lock);
4677
Naresh Tannirud7205b62014-06-20 02:54:48 +05304678exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004679 str = str_parms_to_str(reply);
4680 str_parms_destroy(query);
4681 str_parms_destroy(reply);
4682
4683 ALOGV("%s: exit: returns - %s", __func__, str);
4684 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685}
4686
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004687static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688{
4689 return 0;
4690}
4691
4692static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4693{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004694 int ret;
4695 struct audio_device *adev = (struct audio_device *)dev;
4696 pthread_mutex_lock(&adev->lock);
4697 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004698 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004699 pthread_mutex_unlock(&adev->lock);
4700 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701}
4702
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004703static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4704 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705{
4706 return -ENOSYS;
4707}
4708
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004709static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4710 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711{
4712 return -ENOSYS;
4713}
4714
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004715static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4716 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717{
4718 return -ENOSYS;
4719}
4720
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004721static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4722 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723{
4724 return -ENOSYS;
4725}
4726
4727static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4728{
4729 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731 pthread_mutex_lock(&adev->lock);
4732 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004733 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004734 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004735 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004736 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004737 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004738 adev->current_call_output = NULL;
4739 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 }
4741 pthread_mutex_unlock(&adev->lock);
4742 return 0;
4743}
4744
4745static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4746{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004747 int ret;
4748
4749 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004750 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004751 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4752 pthread_mutex_unlock(&adev->lock);
4753
4754 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004755}
4756
4757static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4758{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004759 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 return 0;
4761}
4762
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004763static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764 const struct audio_config *config)
4765{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004766 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004768 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4769 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770}
4771
4772static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004773 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 audio_devices_t devices,
4775 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004776 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304777 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004778 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004779 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780{
4781 struct audio_device *adev = (struct audio_device *)dev;
4782 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004783 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004784 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004785 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304786 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304789 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4790 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793
4794 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004795
4796 if (!in) {
4797 ALOGE("failed to allocate input stream");
4798 return -ENOMEM;
4799 }
4800
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304801 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304802 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4803 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004804 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004805 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807 in->stream.common.get_sample_rate = in_get_sample_rate;
4808 in->stream.common.set_sample_rate = in_set_sample_rate;
4809 in->stream.common.get_buffer_size = in_get_buffer_size;
4810 in->stream.common.get_channels = in_get_channels;
4811 in->stream.common.get_format = in_get_format;
4812 in->stream.common.set_format = in_set_format;
4813 in->stream.common.standby = in_standby;
4814 in->stream.common.dump = in_dump;
4815 in->stream.common.set_parameters = in_set_parameters;
4816 in->stream.common.get_parameters = in_get_parameters;
4817 in->stream.common.add_audio_effect = in_add_audio_effect;
4818 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4819 in->stream.set_gain = in_set_gain;
4820 in->stream.read = in_read;
4821 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4822
4823 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004824 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004825 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826 in->standby = 1;
4827 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004828 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004829 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304831 in->usecase = USECASE_AUDIO_RECORD;
4832 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4833 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4834 is_low_latency = true;
4835#if LOW_LATENCY_CAPTURE_USE_CASE
4836 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4837#endif
4838 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4839 }
4840
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004841 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004842 if (in->realtime) {
4843 in->config = pcm_config_audio_capture_rt;
4844 in->sample_rate = in->config.rate;
4845 in->af_period_multiplier = af_period_multiplier;
4846 } else {
4847 in->config = pcm_config_audio_capture;
4848 in->config.rate = config->sample_rate;
4849 in->sample_rate = config->sample_rate;
4850 in->af_period_multiplier = 1;
4851 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304852 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304854 /* restrict 24 bit capture for unprocessed source only
4855 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4856 */
4857 if (config->format == AUDIO_FORMAT_DEFAULT) {
4858 config->format = AUDIO_FORMAT_PCM_16_BIT;
4859 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4860 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4861 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4862 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4863 bool ret_error = false;
4864 in->bit_width = 24;
4865 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4866 from HAL is 24_packed and 8_24
4867 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4868 24_packed return error indicating supported format is 24_packed
4869 *> In case of any other source requesting 24 bit or float return error
4870 indicating format supported is 16 bit only.
4871
4872 on error flinger will retry with supported format passed
4873 */
4874 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4875 (source != AUDIO_SOURCE_CAMCORDER)) {
4876 config->format = AUDIO_FORMAT_PCM_16_BIT;
4877 if (config->sample_rate > 48000)
4878 config->sample_rate = 48000;
4879 ret_error = true;
4880 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4881 in->config.format = PCM_FORMAT_S24_3LE;
4882 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4883 in->config.format = PCM_FORMAT_S24_LE;
4884 } else {
4885 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4886 ret_error = true;
4887 }
4888
4889 if (ret_error) {
4890 ret = -EINVAL;
4891 goto err_open;
4892 }
4893 }
4894
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304895 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304896 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4897 (adev->mode != AUDIO_MODE_IN_CALL)) {
4898 ret = -EINVAL;
4899 goto err_open;
4900 }
4901
4902 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4903 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004904 if (config->sample_rate == 0)
4905 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4906 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4907 config->sample_rate != 8000) {
4908 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4909 ret = -EINVAL;
4910 goto err_open;
4911 }
4912 if (config->format == AUDIO_FORMAT_DEFAULT)
4913 config->format = AUDIO_FORMAT_PCM_16_BIT;
4914 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4915 config->format = AUDIO_FORMAT_PCM_16_BIT;
4916 ret = -EINVAL;
4917 goto err_open;
4918 }
4919
4920 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4921 in->config = pcm_config_afe_proxy_record;
4922 in->config.channels = channel_count;
4923 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304924 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304925 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4926 in, config, &channel_mask_updated)) {
4927 if (channel_mask_updated == true) {
4928 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4929 __func__, config->channel_mask);
4930 ret = -EINVAL;
4931 goto err_open;
4932 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304933 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004934 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004935 audio_extn_compr_cap_format_supported(config->format) &&
4936 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004937 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304938 } else if (audio_extn_cin_applicable_stream(in)) {
4939 ret = audio_extn_cin_configure_input_stream(in);
4940 if (ret)
4941 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004942 } else {
4943 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004944 if (!in->realtime) {
4945 in->format = config->format;
4946 frame_size = audio_stream_in_frame_size(&in->stream);
4947 buffer_size = get_input_buffer_size(config->sample_rate,
4948 config->format,
4949 channel_count,
4950 is_low_latency);
4951 in->config.period_size = buffer_size / frame_size;
4952 }
4953
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004954 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004955 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004956 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004957 (in->config.rate == 8000 || in->config.rate == 16000 ||
4958 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004959 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4960 voice_extn_compress_voip_open_input_stream(in);
4961 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004962 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004963
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304964 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4965 &adev->streams_input_cfg_list,
4966 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304967 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304968
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004969 /* This stream could be for sound trigger lab,
4970 get sound trigger pcm if present */
4971 audio_extn_sound_trigger_check_and_get_session(in);
4972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004974 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004975 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976
4977err_open:
4978 free(in);
4979 *stream_in = NULL;
4980 return ret;
4981}
4982
4983static void adev_close_input_stream(struct audio_hw_device *dev,
4984 struct audio_stream_in *stream)
4985{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004986 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004987 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004988 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304989
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304990 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004991
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304992 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004993 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304994
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004995 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304996 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004997 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304998 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004999 if (ret != 0)
5000 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5001 __func__, ret);
5002 } else
5003 in_standby(&stream->common);
5004
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005005 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005006 audio_extn_ssr_deinit();
5007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305009 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005010 audio_extn_compr_cap_format_supported(in->config.format))
5011 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305012
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305013 if (audio_extn_cin_attached_usecase(in->usecase))
5014 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005015
Mingming Yinfd7607b2016-01-22 12:48:44 -08005016 if (in->is_st_session) {
5017 ALOGV("%s: sound trigger pcm stop lab", __func__);
5018 audio_extn_sound_trigger_stop_lab(in);
5019 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005020 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021 return;
5022}
5023
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005024static int adev_dump(const audio_hw_device_t *device __unused,
5025 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026{
5027 return 0;
5028}
5029
5030static int adev_close(hw_device_t *device)
5031{
5032 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005033
5034 if (!adev)
5035 return 0;
5036
5037 pthread_mutex_lock(&adev_init_lock);
5038
5039 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005040 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005041 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305042 audio_extn_utils_release_streams_cfg_lists(
5043 &adev->streams_output_cfg_list,
5044 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305045 if (audio_extn_qaf_is_enabled())
5046 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005047 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005048 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005049 free(adev->snd_dev_ref_cnt);
5050 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005051 if (adev->adm_deinit)
5052 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305053 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005054 free(device);
5055 adev = NULL;
5056 }
5057 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059 return 0;
5060}
5061
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005062/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5063 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5064 * just that it _might_ work.
5065 */
5066static int period_size_is_plausible_for_low_latency(int period_size)
5067{
5068 switch (period_size) {
5069 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005070 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005071 case 240:
5072 case 320:
5073 case 480:
5074 return 1;
5075 default:
5076 return 0;
5077 }
5078}
5079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005080static int adev_open(const hw_module_t *module, const char *name,
5081 hw_device_t **device)
5082{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305083 int ret;
5084
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005085 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5087
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005088 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005089 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005090 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005091 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005092 ALOGD("%s: returning existing instance of adev", __func__);
5093 ALOGD("%s: exit", __func__);
5094 pthread_mutex_unlock(&adev_init_lock);
5095 return 0;
5096 }
5097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 adev = calloc(1, sizeof(struct audio_device));
5099
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005100 if (!adev) {
5101 pthread_mutex_unlock(&adev_init_lock);
5102 return -ENOMEM;
5103 }
5104
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005105 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5108 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5109 adev->device.common.module = (struct hw_module_t *)module;
5110 adev->device.common.close = adev_close;
5111
5112 adev->device.init_check = adev_init_check;
5113 adev->device.set_voice_volume = adev_set_voice_volume;
5114 adev->device.set_master_volume = adev_set_master_volume;
5115 adev->device.get_master_volume = adev_get_master_volume;
5116 adev->device.set_master_mute = adev_set_master_mute;
5117 adev->device.get_master_mute = adev_get_master_mute;
5118 adev->device.set_mode = adev_set_mode;
5119 adev->device.set_mic_mute = adev_set_mic_mute;
5120 adev->device.get_mic_mute = adev_get_mic_mute;
5121 adev->device.set_parameters = adev_set_parameters;
5122 adev->device.get_parameters = adev_get_parameters;
5123 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5124 adev->device.open_output_stream = adev_open_output_stream;
5125 adev->device.close_output_stream = adev_close_output_stream;
5126 adev->device.open_input_stream = adev_open_input_stream;
5127 adev->device.close_input_stream = adev_close_input_stream;
5128 adev->device.dump = adev_dump;
5129
5130 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005132 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005133 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005136 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005137 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005138 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005139 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005140 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005141 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005142 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005143 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305144 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305145 adev->perf_lock_opts[0] = 0x101;
5146 adev->perf_lock_opts[1] = 0x20E;
5147 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305148
5149 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5150 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005152 adev->platform = platform_init(adev);
5153 if (!adev->platform) {
5154 free(adev->snd_dev_ref_cnt);
5155 free(adev);
5156 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5157 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005158 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305159 pthread_mutex_destroy(&adev->lock);
5160 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005161 return -EINVAL;
5162 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005163
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305164 if (audio_extn_qaf_is_enabled()) {
5165 ret = audio_extn_qaf_init(adev);
5166 if (ret < 0) {
5167 free(adev);
5168 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5169 *device = NULL;
5170 pthread_mutex_unlock(&adev_init_lock);
5171 pthread_mutex_destroy(&adev->lock);
5172 return ret;
5173 }
5174
5175 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5176 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5177 }
5178
Naresh Tanniru4c630392014-05-12 01:05:52 +05305179 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5180
Eric Laurentc4aef752013-09-12 17:45:53 -07005181 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5182 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5183 if (adev->visualizer_lib == NULL) {
5184 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5185 } else {
5186 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5187 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005188 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005189 "visualizer_hal_start_output");
5190 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005191 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005192 "visualizer_hal_stop_output");
5193 }
5194 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305195 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005196 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005197 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005198 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005199
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005200 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5201 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5202 if (adev->offload_effects_lib == NULL) {
5203 ALOGE("%s: DLOPEN failed for %s", __func__,
5204 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5205 } else {
5206 ALOGV("%s: DLOPEN successful for %s", __func__,
5207 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5208 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305209 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005210 "offload_effects_bundle_hal_start_output");
5211 adev->offload_effects_stop_output =
5212 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5213 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005214 adev->offload_effects_set_hpx_state =
5215 (int (*)(bool))dlsym(adev->offload_effects_lib,
5216 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305217 adev->offload_effects_get_parameters =
5218 (void (*)(struct str_parms *, struct str_parms *))
5219 dlsym(adev->offload_effects_lib,
5220 "offload_effects_bundle_get_parameters");
5221 adev->offload_effects_set_parameters =
5222 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5223 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005224 }
5225 }
5226
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005227 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5228 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5229 if (adev->adm_lib == NULL) {
5230 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5231 } else {
5232 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5233 adev->adm_init = (adm_init_t)
5234 dlsym(adev->adm_lib, "adm_init");
5235 adev->adm_deinit = (adm_deinit_t)
5236 dlsym(adev->adm_lib, "adm_deinit");
5237 adev->adm_register_input_stream = (adm_register_input_stream_t)
5238 dlsym(adev->adm_lib, "adm_register_input_stream");
5239 adev->adm_register_output_stream = (adm_register_output_stream_t)
5240 dlsym(adev->adm_lib, "adm_register_output_stream");
5241 adev->adm_deregister_stream = (adm_deregister_stream_t)
5242 dlsym(adev->adm_lib, "adm_deregister_stream");
5243 adev->adm_request_focus = (adm_request_focus_t)
5244 dlsym(adev->adm_lib, "adm_request_focus");
5245 adev->adm_abandon_focus = (adm_abandon_focus_t)
5246 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005247 adev->adm_set_config = (adm_set_config_t)
5248 dlsym(adev->adm_lib, "adm_set_config");
5249 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5250 dlsym(adev->adm_lib, "adm_request_focus_v2");
5251 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5252 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5253 adev->adm_on_routing_change = (adm_on_routing_change_t)
5254 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005255 }
5256 }
5257
Mingming Yin514a8bc2014-07-29 15:22:21 -07005258 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005259 //initialize this to false for now,
5260 //this will be set to true through set param
5261 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005262
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005263 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005264 *device = &adev->device.common;
5265
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305266 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5267 &adev->streams_output_cfg_list,
5268 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005269
Kiran Kandi910e1862013-10-29 13:29:42 -07005270 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005271
5272 char value[PROPERTY_VALUE_MAX];
5273 int trial;
5274 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5275 trial = atoi(value);
5276 if (period_size_is_plausible_for_low_latency(trial)) {
5277 pcm_config_low_latency.period_size = trial;
5278 pcm_config_low_latency.start_threshold = trial / 4;
5279 pcm_config_low_latency.avail_min = trial / 4;
5280 configured_low_latency_capture_period_size = trial;
5281 }
5282 }
5283 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5284 trial = atoi(value);
5285 if (period_size_is_plausible_for_low_latency(trial)) {
5286 configured_low_latency_capture_period_size = trial;
5287 }
5288 }
5289
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005290 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5291 af_period_multiplier = atoi(value);
5292 if (af_period_multiplier < 0)
5293 af_period_multiplier = 2;
5294 else if (af_period_multiplier > 4)
5295 af_period_multiplier = 4;
5296
5297 ALOGV("new period_multiplier = %d", af_period_multiplier);
5298 }
5299
vivek mehta446c3962015-09-14 10:57:35 -07005300 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005301 pthread_mutex_unlock(&adev_init_lock);
5302
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005303 if (adev->adm_init)
5304 adev->adm_data = adev->adm_init();
5305
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305306 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305307 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005308 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005309 return 0;
5310}
5311
5312static struct hw_module_methods_t hal_module_methods = {
5313 .open = adev_open,
5314};
5315
5316struct audio_module HAL_MODULE_INFO_SYM = {
5317 .common = {
5318 .tag = HARDWARE_MODULE_TAG,
5319 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5320 .hal_api_version = HARDWARE_HAL_API_VERSION,
5321 .id = AUDIO_HARDWARE_MODULE_ID,
5322 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005323 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324 .methods = &hal_module_methods,
5325 },
5326};