blob: 262fec57b40408ee43fdad268e18700870d668d1 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
609static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
610{
611 ALOGV("%s snd device %d", __func__, snd_device);
612 int new_backend_idx = platform_get_backend_index(snd_device);
613
614 if (((new_backend_idx == HEADPHONE_BACKEND) ||
615 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
616 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
617 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618 struct listnode *node = NULL;
619 struct audio_usecase *uc = NULL;
620 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Garmond Leung50058f62017-02-08 09:49:30 -0800622 int i, num_devices, ret = 0;
623 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530624
625 list_for_each(node, &adev->usecase_list) {
626 uc = node_to_item(node, struct audio_usecase, list);
627 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530628
Garmond Leung50058f62017-02-08 09:49:30 -0800629 if (curr_out && PCM_PLAYBACK == uc->type) {
630 ret = platform_split_snd_device(adev->platform,
631 uc->out_snd_device,
632 &num_devices,
633 split_snd_devices);
634 if (ret < 0 || num_devices == 0) {
635 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
636 split_snd_devices[0] = uc->out_snd_device;
637 num_devices = 1;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530638 }
Garmond Leung50058f62017-02-08 09:49:30 -0800639 for (i = 0; i < num_devices; i++) {
640 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
641 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
642 if((new_backend_idx == HEADPHONE_BACKEND) &&
643 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
644 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
645 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
646 __func__);
647 enable_asrc_mode(adev);
648 break;
649 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
650 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
651 (usecase_backend_idx == HEADPHONE_BACKEND)) {
652 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
653 __func__);
654 disable_audio_route(adev, uc);
655 disable_snd_device(adev, uc->out_snd_device);
656 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
657 if (new_backend_idx == DSD_NATIVE_BACKEND)
658 audio_route_apply_and_update_path(adev->audio_route,
659 "hph-true-highquality-mode");
660 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
661 (curr_out->bit_width >= 24))
662 audio_route_apply_and_update_path(adev->audio_route,
663 "hph-highquality-mode");
664 enable_asrc_mode(adev);
665 enable_snd_device(adev, uc->out_snd_device);
666 enable_audio_route(adev, uc);
667 break;
668 }
669 }
670 // reset split devices count
671 num_devices = 0;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530672 }
Garmond Leung50058f62017-02-08 09:49:30 -0800673 if (adev->asrc_mode_enabled)
674 break;
675
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530676 }
677 }
678}
679
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700680int pcm_ioctl(struct pcm *pcm, int request, ...)
681{
682 va_list ap;
683 void * arg;
684 int pcm_fd = *(int*)pcm;
685
686 va_start(ap, request);
687 arg = va_arg(ap, void *);
688 va_end(ap);
689
690 return ioctl(pcm_fd, request, arg);
691}
692
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700693int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700694 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800695{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700697 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800698
699 if (usecase == NULL)
700 return -EINVAL;
701
702 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
703
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800704 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800709#ifdef DS1_DOLBY_DAP_ENABLED
710 audio_extn_dolby_set_dmid(adev);
711 audio_extn_dolby_set_endpoint(adev);
712#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700713 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700714 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530715 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700716 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530717 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800718 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700719 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700720 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700721 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 ALOGV("%s: exit", __func__);
723 return 0;
724}
725
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700726int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700730 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800731
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530732 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800733 return -EINVAL;
734
735 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 if (usecase->type == PCM_CAPTURE)
737 snd_device = usecase->in_snd_device;
738 else
739 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800740 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700741 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700742 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700744 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530745 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 ALOGV("%s: exit", __func__);
747 return 0;
748}
749
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700750int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700751 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530753 int i, num_devices = 0;
754 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700755 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
756
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 if (snd_device < SND_DEVICE_MIN ||
758 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800759 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800760 return -EINVAL;
761 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762
763 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700764
765 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
766 ALOGE("%s: Invalid sound device returned", __func__);
767 return -EINVAL;
768 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700769 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700770 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700771 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700772 return 0;
773 }
774
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530775
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700776 if (audio_extn_spkr_prot_is_enabled())
777 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700778
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800779 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
780 audio_extn_spkr_prot_is_enabled()) {
781 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700782 adev->snd_dev_ref_cnt[snd_device]--;
783 return -EINVAL;
784 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200785 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800786 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800787 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200788 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800789 return -EINVAL;
790 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700791 } else if (platform_split_snd_device(adev->platform,
792 snd_device,
793 &num_devices,
794 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530795 for (i = 0; i < num_devices; i++) {
796 enable_snd_device(adev, new_snd_devices[i]);
797 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800798 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700799 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530800
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530801 if (platform_check_codec_asrc_support(adev->platform))
802 check_and_set_asrc_mode(adev, snd_device);
803
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530804 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
805 (audio_extn_a2dp_start_playback() < 0)) {
806 ALOGE(" fail to configure A2dp control path ");
807 return -EINVAL;
808 }
809
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700810 /* due to the possibility of calibration overwrite between listen
811 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700812 audio_extn_sound_trigger_update_device_status(snd_device,
813 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530814 audio_extn_listen_update_device_status(snd_device,
815 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700816 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700817 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700818 audio_extn_sound_trigger_update_device_status(snd_device,
819 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530820 audio_extn_listen_update_device_status(snd_device,
821 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700822 return -EINVAL;
823 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300824 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700825 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530826
827 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
828 !adev->native_playback_enabled &&
829 audio_is_true_native_stream_active(adev)) {
830 ALOGD("%s: %d: napb: enabling native mode in hardware",
831 __func__, __LINE__);
832 audio_route_apply_and_update_path(adev->audio_route,
833 "true-native-mode");
834 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 return 0;
838}
839
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700840int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700841 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530843 int i, num_devices = 0;
844 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700845 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
846
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800847 if (snd_device < SND_DEVICE_MIN ||
848 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800849 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 return -EINVAL;
851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
853 ALOGE("%s: device ref cnt is already 0", __func__);
854 return -EINVAL;
855 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700858
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
860 ALOGE("%s: Invalid sound device returned", __func__);
861 return -EINVAL;
862 }
863
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700865 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530866
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800867 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
868 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700869 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700870 } else if (platform_split_snd_device(adev->platform,
871 snd_device,
872 &num_devices,
873 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530874 for (i = 0; i < num_devices; i++) {
875 disable_snd_device(adev, new_snd_devices[i]);
876 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300877 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700878 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300879 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700880
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530881 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
882 audio_extn_a2dp_stop_playback();
883
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700884 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530885 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530886 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
887 adev->native_playback_enabled) {
888 ALOGD("%s: %d: napb: disabling native mode in hardware",
889 __func__, __LINE__);
890 audio_route_reset_and_update_path(adev->audio_route,
891 "true-native-mode");
892 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530893 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
894 adev->asrc_mode_enabled) {
895 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530896 disable_asrc_mode(adev);
897 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530898 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530899
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200900 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700901 audio_extn_sound_trigger_update_device_status(snd_device,
902 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530903 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800904 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800907 return 0;
908}
909
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700910/*
911 legend:
912 uc - existing usecase
913 new_uc - new usecase
914 d1, d11, d2 - SND_DEVICE enums
915 a1, a2 - corresponding ANDROID device enums
916 B1, B2 - backend strings
917
918case 1
919 uc->dev d1 (a1) B1
920 new_uc->dev d1 (a1), d2 (a2) B1, B2
921
922 resolution: disable and enable uc->dev on d1
923
924case 2
925 uc->dev d1 (a1) B1
926 new_uc->dev d11 (a1) B1
927
928 resolution: need to switch uc since d1 and d11 are related
929 (e.g. speaker and voice-speaker)
930 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
931
932case 3
933 uc->dev d1 (a1) B1
934 new_uc->dev d2 (a2) B2
935
936 resolution: no need to switch uc
937
938case 4
939 uc->dev d1 (a1) B1
940 new_uc->dev d2 (a2) B1
941
942 resolution: disable enable uc-dev on d2 since backends match
943 we cannot enable two streams on two different devices if they
944 share the same backend. e.g. if offload is on speaker device using
945 QUAD_MI2S backend and a low-latency stream is started on voice-handset
946 using the same backend, offload must also be switched to voice-handset.
947
948case 5
949 uc->dev d1 (a1) B1
950 new_uc->dev d1 (a1), d2 (a2) B1
951
952 resolution: disable enable uc-dev on d2 since backends match
953 we cannot enable two streams on two different devices if they
954 share the same backend.
955
956case 6
957 uc->dev d1 (a1) B1
958 new_uc->dev d2 (a1) B2
959
960 resolution: no need to switch
961
962case 7
963 uc->dev d1 (a1), d2 (a2) B1, B2
964 new_uc->dev d1 (a1) B1
965
966 resolution: no need to switch
967
968*/
969static snd_device_t derive_playback_snd_device(void * platform,
970 struct audio_usecase *uc,
971 struct audio_usecase *new_uc,
972 snd_device_t new_snd_device)
973{
974 audio_devices_t a1 = uc->stream.out->devices;
975 audio_devices_t a2 = new_uc->stream.out->devices;
976
977 snd_device_t d1 = uc->out_snd_device;
978 snd_device_t d2 = new_snd_device;
979
980 // Treat as a special case when a1 and a2 are not disjoint
981 if ((a1 != a2) && (a1 & a2)) {
982 snd_device_t d3[2];
983 int num_devices = 0;
984 int ret = platform_split_snd_device(platform,
985 popcount(a1) > 1 ? d1 : d2,
986 &num_devices,
987 d3);
988 if (ret < 0) {
989 if (ret != -ENOSYS) {
990 ALOGW("%s failed to split snd_device %d",
991 __func__,
992 popcount(a1) > 1 ? d1 : d2);
993 }
994 goto end;
995 }
996
997 // NB: case 7 is hypothetical and isn't a practical usecase yet.
998 // But if it does happen, we need to give priority to d2 if
999 // the combo devices active on the existing usecase share a backend.
1000 // This is because we cannot have a usecase active on a combo device
1001 // and a new usecase requests one device in this combo pair.
1002 if (platform_check_backends_match(d3[0], d3[1])) {
1003 return d2; // case 5
1004 } else {
1005 return d1; // case 1
1006 }
1007 } else {
1008 if (platform_check_backends_match(d1, d2)) {
1009 return d2; // case 2, 4
1010 } else {
1011 return d1; // case 6, 3
1012 }
1013 }
1014
1015end:
1016 return d2; // return whatever was calculated before.
1017}
1018
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301020 struct audio_usecase *uc_info,
1021 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022{
1023 struct listnode *node;
1024 struct audio_usecase *usecase;
1025 bool switch_device[AUDIO_USECASE_MAX];
1026 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001027 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301028 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 /*
1030 * This function is to make sure that all the usecases that are active on
1031 * the hardware codec backend are always routed to any one device that is
1032 * handled by the hardware codec.
1033 * For example, if low-latency and deep-buffer usecases are currently active
1034 * on speaker and out_set_parameters(headset) is received on low-latency
1035 * output, then we have to make sure deep-buffer is also switched to headset,
1036 * because of the limitation that both the devices cannot be enabled
1037 * at the same time as they share the same backend.
1038 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001039 /*
1040 * This call is to check if we need to force routing for a particular stream
1041 * If there is a backend configuration change for the device when a
1042 * new stream starts, then ADM needs to be closed and re-opened with the new
1043 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001044 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001045 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001046 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1047 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301048 /* For a2dp device reconfigure all active sessions
1049 * with new AFE encoder format based on a2dp state
1050 */
1051 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1052 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1053 audio_extn_a2dp_is_force_device_switch()) {
1054 force_routing = true;
1055 force_restart_session = true;
1056 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301057 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001060 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001061 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1063 switch_device[i] = false;
1064
1065 list_for_each(node, &adev->usecase_list) {
1066 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001067
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301068 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1069 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301070 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301071 platform_get_snd_device_name(usecase->out_snd_device),
1072 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001073 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301074 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001075 (derive_playback_snd_device(adev->platform,
1076 usecase, uc_info,
1077 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301078 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1079 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301080 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301081 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1082 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1083 ((force_restart_session) ||
1084 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301085
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301086 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1087 __func__, use_case_table[usecase->id],
1088 platform_get_snd_device_name(usecase->out_snd_device));
1089 disable_audio_route(adev, usecase);
1090 switch_device[usecase->id] = true;
1091 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 }
1093 }
1094
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1096 num_uc_to_switch);
1097
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001099 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301101 /* Make sure the previous devices to be disabled first and then enable the
1102 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 list_for_each(node, &adev->usecase_list) {
1104 usecase = node_to_item(node, struct audio_usecase, list);
1105 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001106 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 }
1108 }
1109
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001110 list_for_each(node, &adev->usecase_list) {
1111 usecase = node_to_item(node, struct audio_usecase, list);
1112 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001114 }
1115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 /* Re-route all the usecases on the shared backend other than the
1118 specified usecase to new snd devices */
1119 list_for_each(node, &adev->usecase_list) {
1120 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301121 /* Update the out_snd_device only before enabling the audio route */
1122 if (switch_device[usecase->id]) {
1123 usecase->out_snd_device = snd_device;
1124 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301125 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301126 use_case_table[usecase->id],
1127 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001128 /* Update voc calibration before enabling VoIP route */
1129 if (usecase->type == VOIP_CALL)
1130 status = platform_switch_voice_call_device_post(adev->platform,
1131 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001132 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301133 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 }
1136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 }
1138}
1139
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301140static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001141 struct audio_usecase *uc_info,
1142 snd_device_t snd_device)
1143{
1144 struct listnode *node;
1145 struct audio_usecase *usecase;
1146 bool switch_device[AUDIO_USECASE_MAX];
1147 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301148 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001149 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001150
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301151 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1152 snd_device);
1153 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301154
1155 /*
1156 * Make sure out devices is checked against out codec backend device and
1157 * also in devices against in codec backend. Checking out device against in
1158 * codec backend or vice versa causes issues.
1159 */
1160 if (uc_info->type == PCM_CAPTURE)
1161 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 /*
1163 * This function is to make sure that all the active capture usecases
1164 * are always routed to the same input sound device.
1165 * For example, if audio-record and voice-call usecases are currently
1166 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1167 * is received for voice call then we have to make sure that audio-record
1168 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1169 * because of the limitation that two devices cannot be enabled
1170 * at the same time if they share the same backend.
1171 */
1172 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1173 switch_device[i] = false;
1174
1175 list_for_each(node, &adev->usecase_list) {
1176 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301177 /*
1178 * TODO: Enhance below condition to handle BT sco/USB multi recording
1179 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001180 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301182 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301183 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301184 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001185 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001186 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1188 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001189 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001190 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 switch_device[usecase->id] = true;
1192 num_uc_to_switch++;
1193 }
1194 }
1195
1196 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001197 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001198
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301199 /* Make sure the previous devices to be disabled first and then enable the
1200 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001204 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001205 }
1206 }
1207
1208 list_for_each(node, &adev->usecase_list) {
1209 usecase = node_to_item(node, struct audio_usecase, list);
1210 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001211 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 }
1213 }
1214
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 /* Re-route all the usecases on the shared backend other than the
1216 specified usecase to new snd devices */
1217 list_for_each(node, &adev->usecase_list) {
1218 usecase = node_to_item(node, struct audio_usecase, list);
1219 /* Update the in_snd_device only before enabling the audio route */
1220 if (switch_device[usecase->id] ) {
1221 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001222 if (usecase->type != VOICE_CALL) {
1223 /* Update voc calibration before enabling VoIP route */
1224 if (usecase->type == VOIP_CALL)
1225 status = platform_switch_voice_call_device_post(adev->platform,
1226 usecase->out_snd_device,
1227 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301228 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001229 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 }
1231 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 }
1233}
1234
Mingming Yin3a941d42016-02-17 18:08:05 -08001235static void reset_hdmi_sink_caps(struct stream_out *out) {
1236 int i = 0;
1237
1238 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1239 out->supported_channel_masks[i] = 0;
1240 }
1241 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1242 out->supported_formats[i] = 0;
1243 }
1244 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1245 out->supported_sample_rates[i] = 0;
1246 }
1247}
1248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001250static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251{
Mingming Yin3a941d42016-02-17 18:08:05 -08001252 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001253 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254
Mingming Yin3a941d42016-02-17 18:08:05 -08001255 reset_hdmi_sink_caps(out);
1256
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001257 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001258 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001259 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001260 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001261 }
1262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001265 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001266 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001267 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1268 case 6:
1269 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1270 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1271 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1272 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1273 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1274 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 break;
1276 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001277 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001278 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 break;
1280 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001281
1282 // check channel format caps
1283 i = 0;
1284 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1285 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1286 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1287 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1288 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1289 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1290 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1291 }
1292
1293 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1294 ALOGV(":%s HDMI supports DTS format", __func__);
1295 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1296 }
1297
1298 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1299 ALOGV(":%s HDMI supports DTS HD format", __func__);
1300 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1301 }
1302
1303
1304 // check sample rate caps
1305 i = 0;
1306 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1307 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1308 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1309 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1310 }
1311 }
1312
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001313 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314}
1315
Alexy Josephb1379942016-01-29 15:49:38 -08001316audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001317 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001318{
1319 struct audio_usecase *usecase;
1320 struct listnode *node;
1321
1322 list_for_each(node, &adev->usecase_list) {
1323 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001324 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001325 ALOGV("%s: usecase id %d", __func__, usecase->id);
1326 return usecase->id;
1327 }
1328 }
1329 return USECASE_INVALID;
1330}
1331
Alexy Josephb1379942016-01-29 15:49:38 -08001332struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001333 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334{
1335 struct audio_usecase *usecase;
1336 struct listnode *node;
1337
1338 list_for_each(node, &adev->usecase_list) {
1339 usecase = node_to_item(node, struct audio_usecase, list);
1340 if (usecase->id == uc_id)
1341 return usecase;
1342 }
1343 return NULL;
1344}
1345
Dhananjay Kumard4833242016-10-06 22:09:12 +05301346struct stream_in *get_next_active_input(const struct audio_device *adev)
1347{
1348 struct audio_usecase *usecase;
1349 struct listnode *node;
1350
1351 list_for_each_reverse(node, &adev->usecase_list) {
1352 usecase = node_to_item(node, struct audio_usecase, list);
1353 if (usecase->type == PCM_CAPTURE)
1354 return usecase->stream.in;
1355 }
1356 return NULL;
1357}
1358
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301359/*
1360 * is a true native playback active
1361 */
1362bool audio_is_true_native_stream_active(struct audio_device *adev)
1363{
1364 bool active = false;
1365 int i = 0;
1366 struct listnode *node;
1367
1368 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1369 ALOGV("%s:napb: not in true mode or non hdphones device",
1370 __func__);
1371 active = false;
1372 goto exit;
1373 }
1374
1375 list_for_each(node, &adev->usecase_list) {
1376 struct audio_usecase *uc;
1377 uc = node_to_item(node, struct audio_usecase, list);
1378 struct stream_out *curr_out =
1379 (struct stream_out*) uc->stream.out;
1380
1381 if (curr_out && PCM_PLAYBACK == uc->type) {
1382 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1383 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1384 uc->id, curr_out->sample_rate,
1385 curr_out->bit_width,
1386 platform_get_snd_device_name(uc->out_snd_device));
1387
1388 if (is_offload_usecase(uc->id) &&
1389 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1390 active = true;
1391 ALOGD("%s:napb:native stream detected", __func__);
1392 }
1393 }
1394 }
1395exit:
1396 return active;
1397}
1398
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301399/*
1400 * if native DSD playback active
1401 */
1402bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1403{
1404 bool active = false;
1405 struct listnode *node = NULL;
1406 struct audio_usecase *uc = NULL;
1407 struct stream_out *curr_out = NULL;
1408
1409 list_for_each(node, &adev->usecase_list) {
1410 uc = node_to_item(node, struct audio_usecase, list);
1411 curr_out = (struct stream_out*) uc->stream.out;
1412
1413 if (curr_out && PCM_PLAYBACK == uc->type &&
1414 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1415 active = true;
1416 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301417 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301418 }
1419 }
1420 return active;
1421}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301422
1423static bool force_device_switch(struct audio_usecase *usecase)
1424{
1425 bool ret = false;
1426 bool is_it_true_mode = false;
1427
1428 if (is_offload_usecase(usecase->id) &&
1429 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001430 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1431 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1432 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301433 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1434 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1435 (!is_it_true_mode && adev->native_playback_enabled)){
1436 ret = true;
1437 ALOGD("napb: time to toggle native mode");
1438 }
1439 }
1440
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301441 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301442 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1443 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301444 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001445 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301446 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301447 ALOGD("Force a2dp device switch to update new encoder config");
1448 ret = true;
1449 }
1450
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301451 return ret;
1452}
1453
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001454int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 snd_device_t out_snd_device = SND_DEVICE_NONE;
1457 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 struct audio_usecase *usecase = NULL;
1459 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001460 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001461 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001462 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301465 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 usecase = get_usecase_from_list(adev, uc_id);
1468 if (usecase == NULL) {
1469 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1470 return -EINVAL;
1471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001473 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001474 (usecase->type == VOIP_CALL) ||
1475 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301476 if(usecase->stream.out == NULL) {
1477 ALOGE("%s: stream.out is NULL", __func__);
1478 return -EINVAL;
1479 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001480 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001481 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001482 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 usecase->devices = usecase->stream.out->devices;
1484 } else {
1485 /*
1486 * If the voice call is active, use the sound devices of voice call usecase
1487 * so that it would not result any device switch. All the usecases will
1488 * be switched to new device when select_devices() is called for voice call
1489 * usecase. This is to avoid switching devices for voice call when
1490 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001491 * choose voice call device only if the use case device is
1492 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001494 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001495 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001496 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001497 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1498 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301499 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1500 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001501 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 in_snd_device = vc_usecase->in_snd_device;
1503 out_snd_device = vc_usecase->out_snd_device;
1504 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001505 } else if (voice_extn_compress_voip_is_active(adev)) {
1506 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001507 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001508 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1509 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001510 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001511 in_snd_device = voip_usecase->in_snd_device;
1512 out_snd_device = voip_usecase->out_snd_device;
1513 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001514 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001515 hfp_ucid = audio_extn_hfp_get_usecase();
1516 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001517 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001518 in_snd_device = hfp_usecase->in_snd_device;
1519 out_snd_device = hfp_usecase->out_snd_device;
1520 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 }
1522 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301523 if (usecase->stream.out == NULL) {
1524 ALOGE("%s: stream.out is NULL", __func__);
1525 return -EINVAL;
1526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 usecase->devices = usecase->stream.out->devices;
1528 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001529 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001530 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001531 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001532 if (usecase->stream.out == adev->primary_output &&
1533 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001534 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001535 select_devices(adev, adev->active_input->usecase);
1536 }
1537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301539 if (usecase->stream.in == NULL) {
1540 ALOGE("%s: stream.in is NULL", __func__);
1541 return -EINVAL;
1542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 usecase->devices = usecase->stream.in->device;
1544 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001545 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001546 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001547 if (adev->active_input &&
1548 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301549 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1550 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1551 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001552 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001553 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001554 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1555 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001556 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001557 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001558 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 }
1560 }
1561
1562 if (out_snd_device == usecase->out_snd_device &&
1563 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301564
1565 if (!force_device_switch(usecase))
1566 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 }
1568
sangwoobc677242013-08-08 16:53:43 +09001569 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001570 out_snd_device, platform_get_snd_device_name(out_snd_device),
1571 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 /*
1574 * Limitation: While in call, to do a device switch we need to disable
1575 * and enable both RX and TX devices though one of them is same as current
1576 * device.
1577 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001578 if ((usecase->type == VOICE_CALL) &&
1579 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1580 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001581 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001582 }
1583
1584 if (((usecase->type == VOICE_CALL) ||
1585 (usecase->type == VOIP_CALL)) &&
1586 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1587 /* Disable sidetone only if voice/voip call already exists */
1588 if (voice_is_call_state_active(adev) ||
1589 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001590 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001591
1592 /* Disable aanc only if voice call exists */
1593 if (voice_is_call_state_active(adev))
1594 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001595 }
1596
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001597 /* Disable current sound devices */
1598 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001599 disable_audio_route(adev, usecase);
1600 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 }
1602
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 disable_audio_route(adev, usecase);
1605 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 }
1607
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001608 /* Applicable only on the targets that has external modem.
1609 * New device information should be sent to modem before enabling
1610 * the devices to reduce in-call device switch time.
1611 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001612 if ((usecase->type == VOICE_CALL) &&
1613 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1614 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001615 status = platform_switch_voice_call_enable_device_config(adev->platform,
1616 out_snd_device,
1617 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001618 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001619
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 /* Enable new sound devices */
1621 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001622 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001623 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
1625
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001626 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301627 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001628 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001629 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630
Avinash Vaish71a8b972014-07-24 15:36:33 +05301631 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001632 status = platform_switch_voice_call_device_post(adev->platform,
1633 out_snd_device,
1634 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301635 enable_audio_route_for_voice_usecases(adev, usecase);
1636 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001637
sangwoo170731f2013-06-08 15:36:36 +09001638 usecase->in_snd_device = in_snd_device;
1639 usecase->out_snd_device = out_snd_device;
1640
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301641 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1642 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301643 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001644 if ((24 == usecase->stream.out->bit_width) &&
1645 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1646 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1647 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1648 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1649 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1650 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1651 /*
1652 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1653 * configured device sample rate, if not update the COPP rate to be equal to the
1654 * device sample rate, else open COPP at stream sample rate
1655 */
1656 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1657 usecase->stream.out->sample_rate,
1658 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301659 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1660 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001661 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1662 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1663 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1664 }
1665
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001666 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001667 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001668 audio_extn_gef_notify_device_config(
1669 usecase->stream.out->devices,
1670 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001671 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001672 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001673 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301674 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001675 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001676
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001677 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001678 /* Enable aanc only if voice call exists */
1679 if (voice_is_call_state_active(adev))
1680 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1681
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001682 /* Enable sidetone only if other voice/voip call already exists */
1683 if (voice_is_call_state_active(adev) ||
1684 voice_extn_compress_voip_is_started(adev))
1685 voice_set_sidetone(adev, out_snd_device, true);
1686 }
1687
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001688 /* Applicable only on the targets that has external modem.
1689 * Enable device command should be sent to modem only after
1690 * enabling voice call mixer controls
1691 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001692 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001693 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1694 out_snd_device,
1695 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301696 ALOGD("%s: done",__func__);
1697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 return status;
1699}
1700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701static int stop_input_stream(struct stream_in *in)
1702{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301703 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 struct audio_usecase *uc_info;
1705 struct audio_device *adev = in->dev;
1706
Eric Laurent994a6932013-07-17 11:51:42 -07001707 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709 uc_info = get_usecase_from_list(adev, in->usecase);
1710 if (uc_info == NULL) {
1711 ALOGE("%s: Could not find the usecase (%d) in the list",
1712 __func__, in->usecase);
1713 return -EINVAL;
1714 }
1715
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001716 /* Close in-call recording streams */
1717 voice_check_and_stop_incall_rec_usecase(adev, in);
1718
Eric Laurent150dbfe2013-02-27 14:31:02 -08001719 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001720 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001721
1722 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001723 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001725 list_remove(&uc_info->list);
1726 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001728 adev->active_input = get_next_active_input(adev);
1729
Eric Laurent994a6932013-07-17 11:51:42 -07001730 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 return ret;
1732}
1733
1734int start_input_stream(struct stream_in *in)
1735{
1736 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001737 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 struct audio_usecase *uc_info;
1739 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301740 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Mingming Yin2664a5b2015-09-03 10:53:11 -07001742 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1743 if (get_usecase_from_list(adev, usecase) == NULL)
1744 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301745 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1746 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001747
Naresh Tanniru80659832014-06-04 18:17:56 +05301748
1749 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301750 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301751 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301752 goto error_config;
1753 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301754
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001755 /* Check if source matches incall recording usecase criteria */
1756 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1757 if (ret)
1758 goto error_config;
1759 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001760 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1761
1762 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1763 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1764 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001765 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001766 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001767
Eric Laurentb23d5282013-05-14 15:27:20 -07001768 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769 if (in->pcm_device_id < 0) {
1770 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1771 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001772 ret = -EINVAL;
1773 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775
1776 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001778
1779 if (!uc_info) {
1780 ret = -ENOMEM;
1781 goto error_config;
1782 }
1783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 uc_info->id = in->usecase;
1785 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001786 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001787 uc_info->devices = in->device;
1788 uc_info->in_snd_device = SND_DEVICE_NONE;
1789 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001791 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301792 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1793 adev->perf_lock_opts,
1794 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301797 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1798 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001799
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301800 if (audio_extn_cin_attached_usecase(in->usecase)) {
1801 ret = audio_extn_cin_start_input_stream(in);
1802 if (ret)
1803 goto error_open;
1804 else
1805 goto done_open;
1806 }
1807
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001808 unsigned int flags = PCM_IN;
1809 unsigned int pcm_open_retry_count = 0;
1810
1811 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1812 flags |= PCM_MMAP | PCM_NOIRQ;
1813 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001814 } else if (in->realtime) {
1815 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001816 }
1817
1818 while (1) {
1819 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1820 flags, &in->config);
1821 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1822 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1823 if (in->pcm != NULL) {
1824 pcm_close(in->pcm);
1825 in->pcm = NULL;
1826 }
1827 if (pcm_open_retry_count-- == 0) {
1828 ret = -EIO;
1829 goto error_open;
1830 }
1831 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1832 continue;
1833 }
1834 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001836
1837 ALOGV("%s: pcm_prepare", __func__);
1838 ret = pcm_prepare(in->pcm);
1839 if (ret < 0) {
1840 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1841 pcm_close(in->pcm);
1842 in->pcm = NULL;
1843 goto error_open;
1844 }
1845
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001846 register_in_stream(in);
1847 if (in->realtime) {
1848 ret = pcm_start(in->pcm);
1849 if (ret < 0)
1850 goto error_open;
1851 }
1852
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301853done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301854 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001855 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001856
Eric Laurentc8400632013-02-14 19:04:54 -08001857 return ret;
1858
1859error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301860 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001862error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301863 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301864 /*
1865 * sleep 50ms to allow sufficient time for kernel
1866 * drivers to recover incases like SSR.
1867 */
1868 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001870
1871 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872}
1873
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001874void lock_input_stream(struct stream_in *in)
1875{
1876 pthread_mutex_lock(&in->pre_lock);
1877 pthread_mutex_lock(&in->lock);
1878 pthread_mutex_unlock(&in->pre_lock);
1879}
1880
1881void lock_output_stream(struct stream_out *out)
1882{
1883 pthread_mutex_lock(&out->pre_lock);
1884 pthread_mutex_lock(&out->lock);
1885 pthread_mutex_unlock(&out->pre_lock);
1886}
1887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888/* must be called with out->lock locked */
1889static int send_offload_cmd_l(struct stream_out* out, int command)
1890{
1891 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1892
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001893 if (!cmd) {
1894 ALOGE("failed to allocate mem for command 0x%x", command);
1895 return -ENOMEM;
1896 }
1897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 ALOGVV("%s %d", __func__, command);
1899
1900 cmd->cmd = command;
1901 list_add_tail(&out->offload_cmd_list, &cmd->node);
1902 pthread_cond_signal(&out->offload_cond);
1903 return 0;
1904}
1905
1906/* must be called iwth out->lock locked */
1907static void stop_compressed_output_l(struct stream_out *out)
1908{
1909 out->offload_state = OFFLOAD_STATE_IDLE;
1910 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001911 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001912 if (out->compr != NULL) {
1913 compress_stop(out->compr);
1914 while (out->offload_thread_blocked) {
1915 pthread_cond_wait(&out->cond, &out->lock);
1916 }
1917 }
1918}
1919
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001920bool is_offload_usecase(audio_usecase_t uc_id)
1921{
1922 unsigned int i;
1923 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1924 if (uc_id == offload_usecases[i])
1925 return true;
1926 }
1927 return false;
1928}
1929
vivek mehta446c3962015-09-14 10:57:35 -07001930static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001931{
vivek mehta446c3962015-09-14 10:57:35 -07001932 audio_usecase_t ret_uc = USECASE_INVALID;
1933 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001934 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001935 if (!adev->multi_offload_enable) {
1936 if (is_direct_pcm)
1937 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1938 else
1939 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001940
vivek mehta446c3962015-09-14 10:57:35 -07001941 pthread_mutex_lock(&adev->lock);
1942 if (get_usecase_from_list(adev, ret_uc) != NULL)
1943 ret_uc = USECASE_INVALID;
1944 pthread_mutex_unlock(&adev->lock);
1945
1946 return ret_uc;
1947 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001948
1949 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001950 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1951 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1952 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1953 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001954 break;
1955 }
1956 }
vivek mehta446c3962015-09-14 10:57:35 -07001957
1958 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1959 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001960}
1961
1962static void free_offload_usecase(struct audio_device *adev,
1963 audio_usecase_t uc_id)
1964{
vivek mehta446c3962015-09-14 10:57:35 -07001965 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001966 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001967
1968 if (!adev->multi_offload_enable)
1969 return;
1970
1971 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1972 if (offload_usecases[offload_uc_index] == uc_id) {
1973 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001974 break;
1975 }
1976 }
1977 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1978}
1979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980static void *offload_thread_loop(void *context)
1981{
1982 struct stream_out *out = (struct stream_out *) context;
1983 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001984 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001986 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1987 set_sched_policy(0, SP_FOREGROUND);
1988 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1989
1990 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001991 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992 for (;;) {
1993 struct offload_cmd *cmd = NULL;
1994 stream_callback_event_t event;
1995 bool send_callback = false;
1996
1997 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1998 __func__, list_empty(&out->offload_cmd_list),
1999 out->offload_state);
2000 if (list_empty(&out->offload_cmd_list)) {
2001 ALOGV("%s SLEEPING", __func__);
2002 pthread_cond_wait(&out->offload_cond, &out->lock);
2003 ALOGV("%s RUNNING", __func__);
2004 continue;
2005 }
2006
2007 item = list_head(&out->offload_cmd_list);
2008 cmd = node_to_item(item, struct offload_cmd, node);
2009 list_remove(item);
2010
2011 ALOGVV("%s STATE %d CMD %d out->compr %p",
2012 __func__, out->offload_state, cmd->cmd, out->compr);
2013
2014 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2015 free(cmd);
2016 break;
2017 }
2018
2019 if (out->compr == NULL) {
2020 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002021 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 pthread_cond_signal(&out->cond);
2023 continue;
2024 }
2025 out->offload_thread_blocked = true;
2026 pthread_mutex_unlock(&out->lock);
2027 send_callback = false;
2028 switch(cmd->cmd) {
2029 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002030 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002032 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 send_callback = true;
2034 event = STREAM_CBK_EVENT_WRITE_READY;
2035 break;
2036 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002037 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302038 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002039 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302040 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002041 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302042 if (ret < 0)
2043 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302044 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302045 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002046 compress_drain(out->compr);
2047 else
2048 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302049 if (ret != -ENETRESET) {
2050 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302051 pthread_mutex_lock(&out->lock);
2052 out->send_new_metadata = 1;
2053 out->send_next_track_params = true;
2054 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302055 event = STREAM_CBK_EVENT_DRAIN_READY;
2056 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2057 } else
2058 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059 break;
2060 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002061 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002063 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 send_callback = true;
2065 event = STREAM_CBK_EVENT_DRAIN_READY;
2066 break;
2067 default:
2068 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2069 break;
2070 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002071 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002072 out->offload_thread_blocked = false;
2073 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002074 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002075 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002077 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 free(cmd);
2079 }
2080
2081 pthread_cond_signal(&out->cond);
2082 while (!list_empty(&out->offload_cmd_list)) {
2083 item = list_head(&out->offload_cmd_list);
2084 list_remove(item);
2085 free(node_to_item(item, struct offload_cmd, node));
2086 }
2087 pthread_mutex_unlock(&out->lock);
2088
2089 return NULL;
2090}
2091
2092static int create_offload_callback_thread(struct stream_out *out)
2093{
2094 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2095 list_init(&out->offload_cmd_list);
2096 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2097 offload_thread_loop, out);
2098 return 0;
2099}
2100
2101static int destroy_offload_callback_thread(struct stream_out *out)
2102{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002103 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104 stop_compressed_output_l(out);
2105 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2106
2107 pthread_mutex_unlock(&out->lock);
2108 pthread_join(out->offload_thread, (void **) NULL);
2109 pthread_cond_destroy(&out->offload_cond);
2110
2111 return 0;
2112}
2113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114static int stop_output_stream(struct stream_out *out)
2115{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302116 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117 struct audio_usecase *uc_info;
2118 struct audio_device *adev = out->dev;
2119
Eric Laurent994a6932013-07-17 11:51:42 -07002120 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002121 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 uc_info = get_usecase_from_list(adev, out->usecase);
2123 if (uc_info == NULL) {
2124 ALOGE("%s: Could not find the usecase (%d) in the list",
2125 __func__, out->usecase);
2126 return -EINVAL;
2127 }
2128
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302130 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002131 if (adev->visualizer_stop_output != NULL)
2132 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002133
2134 audio_extn_dts_remove_state_notifier_node(out->usecase);
2135
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002136 if (adev->offload_effects_stop_output != NULL)
2137 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2138 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002139
Eric Laurent150dbfe2013-02-27 14:31:02 -08002140 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002141 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002142
2143 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002144 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002146 list_remove(&uc_info->list);
2147 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002149 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302150 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002151 ALOGV("Disable passthrough , reset mixer to pcm");
2152 /* NO_PASSTHROUGH */
2153 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002154 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002155 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2156 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002157
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302158 /* Must be called after removing the usecase from list */
2159 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302160 audio_extn_keep_alive_start();
2161
Eric Laurent994a6932013-07-17 11:51:42 -07002162 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 return ret;
2164}
2165
2166int start_output_stream(struct stream_out *out)
2167{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 struct audio_usecase *uc_info;
2170 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302171 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002173 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2174 ret = -EINVAL;
2175 goto error_config;
2176 }
2177
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302178 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2179 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2180 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302181
Naresh Tanniru80659832014-06-04 18:17:56 +05302182 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302183 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302184 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302185 goto error_config;
2186 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302187
Eric Laurentb23d5282013-05-14 15:27:20 -07002188 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 if (out->pcm_device_id < 0) {
2190 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2191 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002192 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002193 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 }
2195
2196 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002197
2198 if (!uc_info) {
2199 ret = -ENOMEM;
2200 goto error_config;
2201 }
2202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 uc_info->id = out->usecase;
2204 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002205 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002206 uc_info->devices = out->devices;
2207 uc_info->in_snd_device = SND_DEVICE_NONE;
2208 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002209 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302211 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2212 adev->perf_lock_opts,
2213 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302214
2215 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2216 audio_extn_keep_alive_stop();
2217 if (audio_extn_passthru_is_enabled() &&
2218 audio_extn_passthru_is_passthrough_stream(out)) {
2219 audio_extn_passthru_on_start(out);
2220 audio_extn_passthru_update_stream_configuration(adev, out);
2221 }
2222 }
2223
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002224 select_devices(adev, out->usecase);
2225
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002226 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2227 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002228 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002229 unsigned int flags = PCM_OUT;
2230 unsigned int pcm_open_retry_count = 0;
2231 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2232 flags |= PCM_MMAP | PCM_NOIRQ;
2233 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002234 } else if (out->realtime) {
2235 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002236 } else
2237 flags |= PCM_MONOTONIC;
2238
2239 while (1) {
2240 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2241 flags, &out->config);
2242 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2243 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2244 if (out->pcm != NULL) {
2245 pcm_close(out->pcm);
2246 out->pcm = NULL;
2247 }
2248 if (pcm_open_retry_count-- == 0) {
2249 ret = -EIO;
2250 goto error_open;
2251 }
2252 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2253 continue;
2254 }
2255 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002257
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002258 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2259 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002260
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002261 ALOGV("%s: pcm_prepare", __func__);
2262 if (pcm_is_ready(out->pcm)) {
2263 ret = pcm_prepare(out->pcm);
2264 if (ret < 0) {
2265 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2266 pcm_close(out->pcm);
2267 out->pcm = NULL;
2268 goto error_open;
2269 }
2270 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002272 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2273 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002275 out->compr = compress_open(adev->snd_card,
2276 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 COMPRESS_IN, &out->compr_config);
2278 if (out->compr && !is_compress_ready(out->compr)) {
2279 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2280 compress_close(out->compr);
2281 out->compr = NULL;
2282 ret = -EIO;
2283 goto error_open;
2284 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302285 /* compress_open sends params of the track, so reset the flag here */
2286 out->is_compr_metadata_avail = false;
2287
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 if (out->offload_callback)
2289 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002290
Fred Oh3f43e742015-03-04 18:42:34 -08002291 /* Since small bufs uses blocking writes, a write will be blocked
2292 for the default max poll time (20s) in the event of an SSR.
2293 Reduce the poll time to observe and deal with SSR faster.
2294 */
Ashish Jain5106d362016-05-11 19:23:33 +05302295 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002296 compress_set_max_poll_wait(out->compr, 1000);
2297 }
2298
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002299 audio_extn_dts_create_state_notifier_node(out->usecase);
2300 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2301 popcount(out->channel_mask),
2302 out->playback_started);
2303
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002304#ifdef DS1_DOLBY_DDP_ENABLED
2305 if (audio_extn_is_dolby_format(out->format))
2306 audio_extn_dolby_send_ddp_endp_params(adev);
2307#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302308 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2309 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002310 if (adev->visualizer_start_output != NULL)
2311 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2312 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302313 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002314 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002317
2318 if (ret == 0) {
2319 register_out_stream(out);
2320 if (out->realtime) {
2321 ret = pcm_start(out->pcm);
2322 if (ret < 0)
2323 goto error_open;
2324 }
2325 }
2326
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302327 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002328 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002329
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002330 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302332 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002334error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302335 /*
2336 * sleep 50ms to allow sufficient time for kernel
2337 * drivers to recover incases like SSR.
2338 */
2339 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002340 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341}
2342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343static int check_input_parameters(uint32_t sample_rate,
2344 audio_format_t format,
2345 int channel_count)
2346{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002347 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302349 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2350 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2351 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002352 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302353 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002354
2355 switch (channel_count) {
2356 case 1:
2357 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302358 case 3:
2359 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002360 case 6:
2361 break;
2362 default:
2363 ret = -EINVAL;
2364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365
2366 switch (sample_rate) {
2367 case 8000:
2368 case 11025:
2369 case 12000:
2370 case 16000:
2371 case 22050:
2372 case 24000:
2373 case 32000:
2374 case 44100:
2375 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302376 case 96000:
2377 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 break;
2379 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002380 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 }
2382
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002383 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384}
2385
2386static size_t get_input_buffer_size(uint32_t sample_rate,
2387 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002388 int channel_count,
2389 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390{
2391 size_t size = 0;
2392
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002393 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2394 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002396 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002397 if (is_low_latency)
2398 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302399
2400 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002402 /* make sure the size is multiple of 32 bytes
2403 * At 48 kHz mono 16-bit PCM:
2404 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2405 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2406 */
2407 size += 0x1f;
2408 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002409
2410 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411}
2412
Ashish Jain058165c2016-09-28 23:18:48 +05302413static size_t get_output_period_size(uint32_t sample_rate,
2414 audio_format_t format,
2415 int channel_count,
2416 int duration /*in millisecs*/)
2417{
2418 size_t size = 0;
2419 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2420
2421 if ((duration == 0) || (sample_rate == 0) ||
2422 (bytes_per_sample == 0) || (channel_count == 0)) {
2423 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2424 bytes_per_sample, channel_count);
2425 return -EINVAL;
2426 }
2427
2428 size = (sample_rate *
2429 duration *
2430 bytes_per_sample *
2431 channel_count) / 1000;
2432 /*
2433 * To have same PCM samples for all channels, the buffer size requires to
2434 * be multiple of (number of channels * bytes per sample)
2435 * For writes to succeed, the buffer must be written at address which is multiple of 32
2436 */
2437 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2438
2439 return (size/(channel_count * bytes_per_sample));
2440}
2441
Ashish Jain5106d362016-05-11 19:23:33 +05302442static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2443{
2444 uint64_t actual_frames_rendered = 0;
2445 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2446
2447 /* This adjustment accounts for buffering after app processor.
2448 * It is based on estimated DSP latency per use case, rather than exact.
2449 */
2450 int64_t platform_latency = platform_render_latency(out->usecase) *
2451 out->sample_rate / 1000000LL;
2452
2453 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2454 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2455 * hence only estimate.
2456 */
2457 int64_t signed_frames = out->written - kernel_buffer_size;
2458
2459 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2460
2461 if (signed_frames > 0)
2462 actual_frames_rendered = signed_frames;
2463
2464 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2465 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2466 (long long int)out->written, (int)kernel_buffer_size,
2467 audio_bytes_per_sample(out->compr_config.codec->format),
2468 popcount(out->channel_mask));
2469
2470 return actual_frames_rendered;
2471}
2472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2474{
2475 struct stream_out *out = (struct stream_out *)stream;
2476
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002477 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478}
2479
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002480static int out_set_sample_rate(struct audio_stream *stream __unused,
2481 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482{
2483 return -ENOSYS;
2484}
2485
2486static size_t out_get_buffer_size(const struct audio_stream *stream)
2487{
2488 struct stream_out *out = (struct stream_out *)stream;
2489
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002490 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002492 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2493 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302494 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302495 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002496
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002497 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002498 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499}
2500
2501static uint32_t out_get_channels(const struct audio_stream *stream)
2502{
2503 struct stream_out *out = (struct stream_out *)stream;
2504
2505 return out->channel_mask;
2506}
2507
2508static audio_format_t out_get_format(const struct audio_stream *stream)
2509{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002510 struct stream_out *out = (struct stream_out *)stream;
2511
2512 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513}
2514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002515static int out_set_format(struct audio_stream *stream __unused,
2516 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517{
2518 return -ENOSYS;
2519}
2520
2521static int out_standby(struct audio_stream *stream)
2522{
2523 struct stream_out *out = (struct stream_out *)stream;
2524 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002525
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302526 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2527 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002529 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002531 if (adev->adm_deregister_stream)
2532 adev->adm_deregister_stream(adev->adm_data, out->handle);
2533
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002534 if (is_offload_usecase(out->usecase))
2535 stop_compressed_output_l(out);
2536
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002537 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002539 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2540 voice_extn_compress_voip_close_output_stream(stream);
2541 pthread_mutex_unlock(&adev->lock);
2542 pthread_mutex_unlock(&out->lock);
2543 ALOGD("VOIP output entered standby");
2544 return 0;
2545 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 if (out->pcm) {
2547 pcm_close(out->pcm);
2548 out->pcm = NULL;
2549 }
2550 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002551 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302552 out->send_next_track_params = false;
2553 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002554 out->gapless_mdata.encoder_delay = 0;
2555 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 if (out->compr != NULL) {
2557 compress_close(out->compr);
2558 out->compr = NULL;
2559 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002562 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 }
2564 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302565 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 return 0;
2567}
2568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002569static int out_dump(const struct audio_stream *stream __unused,
2570 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571{
2572 return 0;
2573}
2574
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002575static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2576{
2577 int ret = 0;
2578 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002579
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002580 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002581 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002582 return -EINVAL;
2583 }
2584
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302585 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002586
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002587 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2588 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302589 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002590 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002591 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2592 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302593 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002594 }
2595
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002596 ALOGV("%s new encoder delay %u and padding %u", __func__,
2597 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2598
2599 return 0;
2600}
2601
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002602static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2603{
2604 return out == adev->primary_output || out == adev->voice_tx_output;
2605}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610 struct audio_device *adev = out->dev;
2611 struct str_parms *parms;
2612 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002613 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614
sangwoobc677242013-08-08 16:53:43 +09002615 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302618 if (!parms)
2619 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002620 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2621 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002623 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002624 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002626 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002627 * When HDMI cable is unplugged the music playback is paused and
2628 * the policy manager sends routing=0. But the audioflinger continues
2629 * to write data until standby time (3sec). As the HDMI core is
2630 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002631 * Avoid this by routing audio to speaker until standby.
2632 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002633 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2634 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302635 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002636 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2637 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002638 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302639 /*
2640 * When A2DP is disconnected the
2641 * music playback is paused and the policy manager sends routing=0
2642 * But the audioflingercontinues to write data until standby time
2643 * (3sec). As BT is turned off, the write gets blocked.
2644 * Avoid this by routing audio to speaker until standby.
2645 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002646 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302647 (val == AUDIO_DEVICE_NONE)) {
2648 val = AUDIO_DEVICE_OUT_SPEAKER;
2649 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302650 /* To avoid a2dp to sco overlapping force route BT usecases
2651 * to speaker based on Phone state
2652 */
Ashish Jainc597d102016-12-12 10:31:34 +05302653 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2654 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2655 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2656 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302657 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2658 (adev->mode == AUDIO_MODE_IN_CALL))) {
2659 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2660 val = AUDIO_DEVICE_OUT_SPEAKER;
2661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662 /*
2663 * select_devices() call below switches all the usecases on the same
2664 * backend to the new device. Refer to check_usecases_codec_backend() in
2665 * the select_devices(). But how do we undo this?
2666 *
2667 * For example, music playback is active on headset (deep-buffer usecase)
2668 * and if we go to ringtones and select a ringtone, low-latency usecase
2669 * will be started on headset+speaker. As we can't enable headset+speaker
2670 * and headset devices at the same time, select_devices() switches the music
2671 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2672 * So when the ringtone playback is completed, how do we undo the same?
2673 *
2674 * We are relying on the out_set_parameters() call on deep-buffer output,
2675 * once the ringtone playback is ended.
2676 * NOTE: We should not check if the current devices are same as new devices.
2677 * Because select_devices() must be called to switch back the music
2678 * playback to headset.
2679 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002680 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002681 audio_devices_t new_dev = val;
2682 bool same_dev = out->devices == new_dev;
2683 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002684
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002685 if (output_drives_call(adev, out)) {
2686 if(!voice_is_in_call(adev)) {
2687 if (adev->mode == AUDIO_MODE_IN_CALL) {
2688 adev->current_call_output = out;
2689 ret = voice_start_call(adev);
2690 }
2691 } else {
2692 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002693 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002694 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002695 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002696
2697 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002698 if (!same_dev) {
2699 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302700 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2701 adev->perf_lock_opts,
2702 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002703 if (adev->adm_on_routing_change)
2704 adev->adm_on_routing_change(adev->adm_data,
2705 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002706 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002707 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302708 if (!same_dev)
2709 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002710 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002711 }
2712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002714 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002716
2717 if (out == adev->primary_output) {
2718 pthread_mutex_lock(&adev->lock);
2719 audio_extn_set_parameters(adev, parms);
2720 pthread_mutex_unlock(&adev->lock);
2721 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002722 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002723 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002724 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002725
2726 audio_extn_dts_create_state_notifier_node(out->usecase);
2727 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2728 popcount(out->channel_mask),
2729 out->playback_started);
2730
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002731 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002732 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002733
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302734 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2735 if (err >= 0) {
2736 strlcpy(out->profile, value, sizeof(out->profile));
2737 ALOGV("updating stream profile with value '%s'", out->profile);
2738 lock_output_stream(out);
2739 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2740 &adev->streams_output_cfg_list,
2741 out->devices, out->flags, out->format,
2742 out->sample_rate, out->bit_width,
2743 out->channel_mask, out->profile,
2744 &out->app_type_cfg);
2745 pthread_mutex_unlock(&out->lock);
2746 }
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302749error:
Eric Laurent994a6932013-07-17 11:51:42 -07002750 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 return ret;
2752}
2753
2754static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2755{
2756 struct stream_out *out = (struct stream_out *)stream;
2757 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002758 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 char value[256];
2760 struct str_parms *reply = str_parms_create();
2761 size_t i, j;
2762 int ret;
2763 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002764
2765 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002766 if (reply) {
2767 str_parms_destroy(reply);
2768 }
2769 if (query) {
2770 str_parms_destroy(query);
2771 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002772 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2773 return NULL;
2774 }
2775
Eric Laurent994a6932013-07-17 11:51:42 -07002776 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2778 if (ret >= 0) {
2779 value[0] = '\0';
2780 i = 0;
2781 while (out->supported_channel_masks[i] != 0) {
2782 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2783 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2784 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002785 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002787 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 first = false;
2789 break;
2790 }
2791 }
2792 i++;
2793 }
2794 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2795 str = str_parms_to_str(reply);
2796 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002797 voice_extn_out_get_parameters(out, query, reply);
2798 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002799 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002800 free(str);
2801 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002802 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002804
Alexy Joseph62142aa2015-11-16 15:10:34 -08002805
2806 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2807 if (ret >= 0) {
2808 value[0] = '\0';
2809 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2810 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302811 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002812 } else {
2813 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302814 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002815 }
2816 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002817 if (str)
2818 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002819 str = str_parms_to_str(reply);
2820 }
2821
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002822 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2823 if (ret >= 0) {
2824 value[0] = '\0';
2825 i = 0;
2826 first = true;
2827 while (out->supported_formats[i] != 0) {
2828 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2829 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2830 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002831 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002832 }
2833 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2834 first = false;
2835 break;
2836 }
2837 }
2838 i++;
2839 }
2840 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002841 if (str)
2842 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002843 str = str_parms_to_str(reply);
2844 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002845
2846 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2847 if (ret >= 0) {
2848 value[0] = '\0';
2849 i = 0;
2850 first = true;
2851 while (out->supported_sample_rates[i] != 0) {
2852 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2853 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2854 if (!first) {
2855 strlcat(value, "|", sizeof(value));
2856 }
2857 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2858 first = false;
2859 break;
2860 }
2861 }
2862 i++;
2863 }
2864 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2865 if (str)
2866 free(str);
2867 str = str_parms_to_str(reply);
2868 }
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 str_parms_destroy(query);
2871 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002872 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 return str;
2874}
2875
2876static uint32_t out_get_latency(const struct audio_stream_out *stream)
2877{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002878 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002880 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881
Alexy Josephaa54c872014-12-03 02:46:47 -08002882 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002883 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002884 } else if (out->realtime) {
2885 // since the buffer won't be filled up faster than realtime,
2886 // return a smaller number
2887 if (out->config.rate)
2888 period_ms = (out->af_period_multiplier * out->config.period_size *
2889 1000) / (out->config.rate);
2890 else
2891 period_ms = 0;
2892 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002893 } else {
2894 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002896 }
2897
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002898 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2899 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2900 latency += audio_extn_a2dp_get_encoder_latency();
2901
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302902 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002903 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904}
2905
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302906static float AmpToDb(float amplification)
2907{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302908 float db = DSD_VOLUME_MIN_DB;
2909 if (amplification > 0) {
2910 db = 20 * log10(amplification);
2911 if(db < DSD_VOLUME_MIN_DB)
2912 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302913 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302914 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302915}
2916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917static int out_set_volume(struct audio_stream_out *stream, float left,
2918 float right)
2919{
Eric Laurenta9024de2013-04-04 09:19:12 -07002920 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 int volume[2];
2922
Eric Laurenta9024de2013-04-04 09:19:12 -07002923 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2924 /* only take left channel into account: the API is for stereo anyway */
2925 out->muted = (left == 0.0f);
2926 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002927 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302928 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002929 /*
2930 * Set mute or umute on HDMI passthrough stream.
2931 * Only take left channel into account.
2932 * Mute is 0 and unmute 1
2933 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302934 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302935 } else if (out->format == AUDIO_FORMAT_DSD){
2936 char mixer_ctl_name[128] = "DSD Volume";
2937 struct audio_device *adev = out->dev;
2938 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2939
2940 if (!ctl) {
2941 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2942 __func__, mixer_ctl_name);
2943 return -EINVAL;
2944 }
2945 volume[0] = (int)(AmpToDb(left));
2946 volume[1] = (int)(AmpToDb(right));
2947 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2948 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002949 } else {
2950 char mixer_ctl_name[128];
2951 struct audio_device *adev = out->dev;
2952 struct mixer_ctl *ctl;
2953 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002954 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002956 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2957 "Compress Playback %d Volume", pcm_device_id);
2958 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2959 if (!ctl) {
2960 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2961 __func__, mixer_ctl_name);
2962 return -EINVAL;
2963 }
2964 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2965 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2966 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2967 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002968 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002969 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 return -ENOSYS;
2972}
2973
2974static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2975 size_t bytes)
2976{
2977 struct stream_out *out = (struct stream_out *)stream;
2978 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302979 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002980 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002982 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302983
Naresh Tanniru80659832014-06-04 18:17:56 +05302984 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002985
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302986 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302987 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302988 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2989 pthread_mutex_unlock(&out->lock);
2990 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302991 } else {
2992 /* increase written size during SSR to avoid mismatch
2993 * with the written frames count in AF
2994 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002995 // bytes per frame
2996 size_t bpf = audio_bytes_per_sample(out->format) *
2997 audio_channel_count_from_out_mask(out->channel_mask);
2998 if (bpf != 0)
2999 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303000 ALOGD(" %s: sound card is not active/SSR state", __func__);
3001 ret= -EIO;
3002 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303003 }
3004 }
3005
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303006 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303007 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3008 if (audio_bytes_per_sample(out->format) != 0)
3009 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3010 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303011 goto exit;
3012 }
3013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003015 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003016 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003017 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3018 ret = voice_extn_compress_voip_start_output_stream(out);
3019 else
3020 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003021 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003024 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 goto exit;
3026 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003027
3028 if (last_known_cal_step != -1) {
3029 ALOGD("%s: retry previous failed cal level set", __func__);
3030 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033
Ashish Jain81eb2a82015-05-13 10:52:34 +05303034 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003035 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303036 adev->is_channel_status_set = true;
3037 }
3038
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003039 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003040 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003041 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003042 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003043 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3044 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303045 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3046 ALOGD("copl(%p):send next track params in gapless", out);
3047 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3048 out->send_next_track_params = false;
3049 out->is_compr_metadata_avail = false;
3050 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003051 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303052 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303053 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003054
Ashish Jain83a6cc22016-06-28 14:34:17 +05303055 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303056 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303057 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303058 pthread_mutex_unlock(&out->lock);
3059 return -EINVAL;
3060 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303061 audio_format_t dst_format = out->hal_op_format;
3062 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303063
3064 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3065 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3066
Ashish Jain83a6cc22016-06-28 14:34:17 +05303067 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303068 dst_format,
3069 buffer,
3070 src_format,
3071 frames);
3072
Ashish Jain83a6cc22016-06-28 14:34:17 +05303073 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303074 bytes_to_write);
3075
3076 /*Convert written bytes in audio flinger format*/
3077 if (ret > 0)
3078 ret = ((ret * format_to_bitwidth_table[out->format]) /
3079 format_to_bitwidth_table[dst_format]);
3080 }
3081 } else
3082 ret = compress_write(out->compr, buffer, bytes);
3083
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303084 if (ret < 0)
3085 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303086 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303087 /*msg to cb thread only if non blocking write is enabled*/
3088 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303089 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303091 } else if (-ENETRESET == ret) {
3092 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3093 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3094 pthread_mutex_unlock(&out->lock);
3095 out_standby(&out->stream.common);
3096 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 }
Ashish Jain5106d362016-05-11 19:23:33 +05303098 if ( ret == (ssize_t)bytes && !out->non_blocking)
3099 out->written += bytes;
3100
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303101 /* Call compr start only when non-zero bytes of data is there to be rendered */
3102 if (!out->playback_started && ret > 0) {
3103 int status = compress_start(out->compr);
3104 if (status < 0) {
3105 ret = status;
3106 ALOGE("%s: compr start failed with err %d", __func__, errno);
3107 goto exit;
3108 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003109 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 out->playback_started = 1;
3111 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003112
3113 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3114 popcount(out->channel_mask),
3115 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 }
3117 pthread_mutex_unlock(&out->lock);
3118 return ret;
3119 } else {
3120 if (out->pcm) {
3121 if (out->muted)
3122 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003123
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303124 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003125
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003126 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003127
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003128 if (out->config.rate)
3129 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3130 out->config.rate;
3131
3132 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3133
3134 request_out_focus(out, ns);
3135
3136 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003137 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003138 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303139 out->convert_buffer != NULL) {
3140
3141 memcpy_by_audio_format(out->convert_buffer,
3142 out->hal_op_format,
3143 buffer,
3144 out->hal_ip_format,
3145 out->config.period_size * out->config.channels);
3146
3147 ret = pcm_write(out->pcm, out->convert_buffer,
3148 (out->config.period_size *
3149 out->config.channels *
3150 format_to_bitwidth_table[out->hal_op_format]));
3151 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003152 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303153 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003154
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003155 release_out_focus(out);
3156
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303157 if (ret < 0)
3158 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303159 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3160 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3161 else
3162 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 }
3165
3166exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303167 /* ToDo: There may be a corner case when SSR happens back to back during
3168 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303169 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303170 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303171 }
3172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 pthread_mutex_unlock(&out->lock);
3174
3175 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003176 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003177 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303178 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303179 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303180 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303181 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303182 out->standby = true;
3183 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303185 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3186 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3187 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 }
3189 return bytes;
3190}
3191
3192static int out_get_render_position(const struct audio_stream_out *stream,
3193 uint32_t *dsp_frames)
3194{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003195 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303196 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003197
3198 if (dsp_frames == NULL)
3199 return -EINVAL;
3200
3201 *dsp_frames = 0;
3202 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003203 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303204
3205 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3206 * this operation and adev_close_output_stream(where out gets reset).
3207 */
3208 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3209 *dsp_frames = get_actual_pcm_frames_rendered(out);
3210 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3211 return 0;
3212 }
3213
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003214 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303215 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303216 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303218 if (ret < 0)
3219 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003220 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303221 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003222 }
3223 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303224 if (-ENETRESET == ret) {
3225 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3226 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3227 return -EINVAL;
3228 } else if(ret < 0) {
3229 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3230 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303231 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3232 /*
3233 * Handle corner case where compress session is closed during SSR
3234 * and timestamp is queried
3235 */
3236 ALOGE(" ERROR: sound card not active, return error");
3237 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303238 } else {
3239 return 0;
3240 }
Zhou Song32a556e2015-05-05 10:46:56 +08003241 } else if (audio_is_linear_pcm(out->format)) {
3242 *dsp_frames = out->written;
3243 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244 } else
3245 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246}
3247
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003248static int out_add_audio_effect(const struct audio_stream *stream __unused,
3249 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250{
3251 return 0;
3252}
3253
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003254static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3255 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256{
3257 return 0;
3258}
3259
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003260static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3261 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262{
3263 return -EINVAL;
3264}
3265
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003266static int out_get_presentation_position(const struct audio_stream_out *stream,
3267 uint64_t *frames, struct timespec *timestamp)
3268{
3269 struct stream_out *out = (struct stream_out *)stream;
3270 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003271 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003272
Ashish Jain5106d362016-05-11 19:23:33 +05303273 /* below piece of code is not guarded against any lock because audioFliner serializes
3274 * this operation and adev_close_output_stream( where out gets reset).
3275 */
3276 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3277 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3278 *frames = get_actual_pcm_frames_rendered(out);
3279 /* this is the best we can do */
3280 clock_gettime(CLOCK_MONOTONIC, timestamp);
3281 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3282 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3283 return 0;
3284 }
3285
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003286 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003287
Ashish Jain5106d362016-05-11 19:23:33 +05303288 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3289 ret = compress_get_tstamp(out->compr, &dsp_frames,
3290 &out->sample_rate);
3291 ALOGVV("%s rendered frames %ld sample_rate %d",
3292 __func__, dsp_frames, out->sample_rate);
3293 *frames = dsp_frames;
3294 if (ret < 0)
3295 ret = -errno;
3296 if (-ENETRESET == ret) {
3297 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3298 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3299 ret = -EINVAL;
3300 } else
3301 ret = 0;
3302 /* this is the best we can do */
3303 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003304 } else {
3305 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003306 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003307 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3308 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003309 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003310 // This adjustment accounts for buffering after app processor.
3311 // It is based on estimated DSP latency per use case, rather than exact.
3312 signed_frames -=
3313 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3314
Eric Laurent949a0892013-09-20 09:20:13 -07003315 // It would be unusual for this value to be negative, but check just in case ...
3316 if (signed_frames >= 0) {
3317 *frames = signed_frames;
3318 ret = 0;
3319 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003320 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303321 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3322 *frames = out->written;
3323 clock_gettime(CLOCK_MONOTONIC, timestamp);
3324 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003325 }
3326 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003327 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003328 return ret;
3329}
3330
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003331static int out_set_callback(struct audio_stream_out *stream,
3332 stream_callback_t callback, void *cookie)
3333{
3334 struct stream_out *out = (struct stream_out *)stream;
3335
3336 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003337 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338 out->offload_callback = callback;
3339 out->offload_cookie = cookie;
3340 pthread_mutex_unlock(&out->lock);
3341 return 0;
3342}
3343
3344static int out_pause(struct audio_stream_out* stream)
3345{
3346 struct stream_out *out = (struct stream_out *)stream;
3347 int status = -ENOSYS;
3348 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003349 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003350 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003351 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003352 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303353 struct audio_device *adev = out->dev;
3354 int snd_scard_state = get_snd_card_state(adev);
3355
3356 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3357 status = compress_pause(out->compr);
3358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003359 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003360
Mingming Yin21854652016-04-13 11:54:02 -07003361 if (audio_extn_passthru_is_active()) {
3362 ALOGV("offload use case, pause passthru");
3363 audio_extn_passthru_on_pause(out);
3364 }
3365
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303366 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003367 audio_extn_dts_notify_playback_state(out->usecase, 0,
3368 out->sample_rate, popcount(out->channel_mask),
3369 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003370 }
3371 pthread_mutex_unlock(&out->lock);
3372 }
3373 return status;
3374}
3375
3376static int out_resume(struct audio_stream_out* stream)
3377{
3378 struct stream_out *out = (struct stream_out *)stream;
3379 int status = -ENOSYS;
3380 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003381 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003382 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003384 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303386 struct audio_device *adev = out->dev;
3387 int snd_scard_state = get_snd_card_state(adev);
3388
Mingming Yin21854652016-04-13 11:54:02 -07003389 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3390 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3391 pthread_mutex_lock(&out->dev->lock);
3392 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003393 pthread_mutex_unlock(&out->dev->lock);
3394 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303395 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003396 }
3397 if (!status) {
3398 out->offload_state = OFFLOAD_STATE_PLAYING;
3399 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303400 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003401 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3402 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003403 }
3404 pthread_mutex_unlock(&out->lock);
3405 }
3406 return status;
3407}
3408
3409static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3410{
3411 struct stream_out *out = (struct stream_out *)stream;
3412 int status = -ENOSYS;
3413 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003414 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003415 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3417 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3418 else
3419 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3420 pthread_mutex_unlock(&out->lock);
3421 }
3422 return status;
3423}
3424
3425static int out_flush(struct audio_stream_out* stream)
3426{
3427 struct stream_out *out = (struct stream_out *)stream;
3428 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003429 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003430 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003431 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003432 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3433 stop_compressed_output_l(out);
3434 out->written = 0;
3435 } else {
3436 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3437 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003438 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003439 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440 return 0;
3441 }
3442 return -ENOSYS;
3443}
3444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445/** audio_stream_in implementation **/
3446static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3447{
3448 struct stream_in *in = (struct stream_in *)stream;
3449
3450 return in->config.rate;
3451}
3452
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003453static int in_set_sample_rate(struct audio_stream *stream __unused,
3454 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455{
3456 return -ENOSYS;
3457}
3458
3459static size_t in_get_buffer_size(const struct audio_stream *stream)
3460{
3461 struct stream_in *in = (struct stream_in *)stream;
3462
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003463 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3464 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003465 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3466 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303467 else if(audio_extn_cin_attached_usecase(in->usecase))
3468 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003469
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003470 return in->config.period_size * in->af_period_multiplier *
3471 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472}
3473
3474static uint32_t in_get_channels(const struct audio_stream *stream)
3475{
3476 struct stream_in *in = (struct stream_in *)stream;
3477
3478 return in->channel_mask;
3479}
3480
3481static audio_format_t in_get_format(const struct audio_stream *stream)
3482{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003483 struct stream_in *in = (struct stream_in *)stream;
3484
3485 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486}
3487
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003488static int in_set_format(struct audio_stream *stream __unused,
3489 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490{
3491 return -ENOSYS;
3492}
3493
3494static int in_standby(struct audio_stream *stream)
3495{
3496 struct stream_in *in = (struct stream_in *)stream;
3497 struct audio_device *adev = in->dev;
3498 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303499 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3500 stream, in->usecase, use_case_table[in->usecase]);
3501
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003502 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003503 if (!in->standby && in->is_st_session) {
3504 ALOGD("%s: sound trigger pcm stop lab", __func__);
3505 audio_extn_sound_trigger_stop_lab(in);
3506 in->standby = 1;
3507 }
3508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003510 if (adev->adm_deregister_stream)
3511 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3512
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003513 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003515 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3516 voice_extn_compress_voip_close_input_stream(stream);
3517 ALOGD("VOIP input entered standby");
3518 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303519 if (audio_extn_cin_attached_usecase(in->usecase))
3520 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003521 if (in->pcm) {
3522 pcm_close(in->pcm);
3523 in->pcm = NULL;
3524 }
3525 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003526 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003527 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 }
3529 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003530 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 return status;
3532}
3533
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003534static int in_dump(const struct audio_stream *stream __unused,
3535 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536{
3537 return 0;
3538}
3539
3540static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3541{
3542 struct stream_in *in = (struct stream_in *)stream;
3543 struct audio_device *adev = in->dev;
3544 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003546 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303548 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 parms = str_parms_create_str(kvpairs);
3550
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303551 if (!parms)
3552 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003553 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003554 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003555
3556 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3557 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 val = atoi(value);
3559 /* no audio source uses val == 0 */
3560 if ((in->source != val) && (val != 0)) {
3561 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003562 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3563 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3564 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003565 (in->config.rate == 8000 || in->config.rate == 16000 ||
3566 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003567 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003568 err = voice_extn_compress_voip_open_input_stream(in);
3569 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003570 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003571 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003572 }
3573 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 }
3575 }
3576
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003577 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3578 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003580 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 in->device = val;
3582 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003583 if (!in->standby && !in->is_st_session) {
3584 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003585 if (adev->adm_on_routing_change)
3586 adev->adm_on_routing_change(adev->adm_data,
3587 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003588 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 }
3591 }
3592
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303593 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3594 if (err >= 0) {
3595 strlcpy(in->profile, value, sizeof(in->profile));
3596 ALOGV("updating stream profile with value '%s'", in->profile);
3597 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3598 &adev->streams_input_cfg_list,
3599 in->device, in->flags, in->format,
3600 in->sample_rate, in->bit_width,
3601 in->profile, &in->app_type_cfg);
3602 }
3603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003605 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606
3607 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303608error:
Eric Laurent994a6932013-07-17 11:51:42 -07003609 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 return ret;
3611}
3612
3613static char* in_get_parameters(const struct audio_stream *stream,
3614 const char *keys)
3615{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003616 struct stream_in *in = (struct stream_in *)stream;
3617 struct str_parms *query = str_parms_create_str(keys);
3618 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003619 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003620
3621 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003622 if (reply) {
3623 str_parms_destroy(reply);
3624 }
3625 if (query) {
3626 str_parms_destroy(query);
3627 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003628 ALOGE("in_get_parameters: failed to create query or reply");
3629 return NULL;
3630 }
3631
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003632 ALOGV("%s: enter: keys - %s", __func__, keys);
3633
3634 voice_extn_in_get_parameters(in, query, reply);
3635
3636 str = str_parms_to_str(reply);
3637 str_parms_destroy(query);
3638 str_parms_destroy(reply);
3639
3640 ALOGV("%s: exit: returns - %s", __func__, str);
3641 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642}
3643
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003644static int in_set_gain(struct audio_stream_in *stream __unused,
3645 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
3647 return 0;
3648}
3649
3650static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3651 size_t bytes)
3652{
3653 struct stream_in *in = (struct stream_in *)stream;
3654 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303655 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303656 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303657 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003659 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303660
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003661 if (in->is_st_session) {
3662 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3663 /* Read from sound trigger HAL */
3664 audio_extn_sound_trigger_read(in, buffer, bytes);
3665 pthread_mutex_unlock(&in->lock);
3666 return bytes;
3667 }
3668
Ashish Jainbbce4322016-02-16 13:25:27 +05303669 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003670 ALOGD(" %s: sound card is not active/SSR state", __func__);
3671 ret= -EIO;;
3672 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303673 }
3674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003676 pthread_mutex_lock(&adev->lock);
3677 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3678 ret = voice_extn_compress_voip_start_input_stream(in);
3679 else
3680 ret = start_input_stream(in);
3681 pthread_mutex_unlock(&adev->lock);
3682 if (ret != 0) {
3683 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 }
3685 in->standby = 0;
3686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003688 // what's the duration requested by the client?
3689 long ns = 0;
3690
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303691 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003692 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3693 in->config.rate;
3694
3695 request_in_focus(in, ns);
3696 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003697
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303698 if (audio_extn_cin_attached_usecase(in->usecase)) {
3699 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3700 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303701 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003702 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303703 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003704 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003705 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003706 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303707 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003708 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303709 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3710 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3711 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3712 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303713 ret = -EINVAL;
3714 goto exit;
3715 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303716 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303717 ret = -errno;
3718 }
3719 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303720 /* bytes read is always set to bytes for non compress usecases */
3721 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 }
3723
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003724 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 /*
3727 * Instead of writing zeroes here, we could trust the hardware
3728 * to always provide zeroes when muted.
3729 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303730 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3731 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 memset(buffer, 0, bytes);
3733
3734exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303735 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303736 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003737 if (-ENETRESET == ret)
3738 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 pthread_mutex_unlock(&in->lock);
3741
3742 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303743 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303744 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303745 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303746 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303747 in->standby = true;
3748 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303749 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003751 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303752 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303753 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303755 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756}
3757
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003758static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759{
3760 return 0;
3761}
3762
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003763static int add_remove_audio_effect(const struct audio_stream *stream,
3764 effect_handle_t effect,
3765 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003767 struct stream_in *in = (struct stream_in *)stream;
3768 int status = 0;
3769 effect_descriptor_t desc;
3770
3771 status = (*effect)->get_descriptor(effect, &desc);
3772 if (status != 0)
3773 return status;
3774
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003775 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003776 pthread_mutex_lock(&in->dev->lock);
3777 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3778 in->enable_aec != enable &&
3779 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3780 in->enable_aec = enable;
3781 if (!in->standby)
3782 select_devices(in->dev, in->usecase);
3783 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003784 if (in->enable_ns != enable &&
3785 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3786 in->enable_ns = enable;
3787 if (!in->standby)
3788 select_devices(in->dev, in->usecase);
3789 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003790 pthread_mutex_unlock(&in->dev->lock);
3791 pthread_mutex_unlock(&in->lock);
3792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 return 0;
3794}
3795
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003796static int in_add_audio_effect(const struct audio_stream *stream,
3797 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798{
Eric Laurent994a6932013-07-17 11:51:42 -07003799 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003800 return add_remove_audio_effect(stream, effect, true);
3801}
3802
3803static int in_remove_audio_effect(const struct audio_stream *stream,
3804 effect_handle_t effect)
3805{
Eric Laurent994a6932013-07-17 11:51:42 -07003806 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003807 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808}
3809
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303810int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 audio_io_handle_t handle,
3812 audio_devices_t devices,
3813 audio_output_flags_t flags,
3814 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003815 struct audio_stream_out **stream_out,
3816 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817{
3818 struct audio_device *adev = (struct audio_device *)dev;
3819 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303820 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003821 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303824
3825 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3826 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003827 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303828 return -EINVAL;
3829 }
3830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3832
Mingming Yin3a941d42016-02-17 18:08:05 -08003833 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3834 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303835 devices, flags, &out->stream);
3836
3837
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003838 if (!out) {
3839 return -ENOMEM;
3840 }
3841
Haynes Mathew George204045b2015-02-25 20:32:03 -08003842 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003843 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003844 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 if (devices == AUDIO_DEVICE_NONE)
3847 devices = AUDIO_DEVICE_OUT_SPEAKER;
3848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 out->flags = flags;
3850 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003851 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003852 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 out->sample_rate = config->sample_rate;
3854 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3855 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003856 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003857 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003858 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303859 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860
Mingming Yin3a941d42016-02-17 18:08:05 -08003861 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3862 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3863 pthread_mutex_lock(&adev->lock);
3864 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3865 ret = read_hdmi_sink_caps(out);
3866 pthread_mutex_unlock(&adev->lock);
3867 if (ret != 0) {
3868 if (ret == -ENOSYS) {
3869 /* ignore and go with default */
3870 ret = 0;
3871 } else {
3872 ALOGE("error reading hdmi sink caps");
3873 goto error_open;
3874 }
3875 }
3876 }
3877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003879 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303880 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3881 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003882 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3883 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3884
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003885 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003886 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3887 /*
3888 * Do not handle stereo output in Multi-channel cases
3889 * Stereo case is handled in normal playback path
3890 */
3891 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3892 ret = AUDIO_CHANNEL_OUT_STEREO;
3893 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003894
3895 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3896 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003897 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003898 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003899 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003900
3901 if (config->sample_rate == 0)
3902 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3903 if (config->channel_mask == 0)
3904 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003905 if (config->format == 0)
3906 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003907
3908 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003909 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003910 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3912 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003914 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003916 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003917 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003918 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003919 ret = voice_extn_compress_voip_open_output_stream(out);
3920 if (ret != 0) {
3921 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3922 __func__, ret);
3923 goto error_open;
3924 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003925 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3926 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003928 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3929 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3930 ALOGE("%s: Unsupported Offload information", __func__);
3931 ret = -EINVAL;
3932 goto error_open;
3933 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003934
Mingming Yin3a941d42016-02-17 18:08:05 -08003935 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003936 if(config->offload_info.format == 0)
3937 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003938 if (config->offload_info.sample_rate == 0)
3939 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003940 }
3941
Mingming Yin90310102013-11-13 16:57:00 -08003942 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303943 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003944 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003945 ret = -EINVAL;
3946 goto error_open;
3947 }
3948
3949 out->compr_config.codec = (struct snd_codec *)
3950 calloc(1, sizeof(struct snd_codec));
3951
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003952 if (!out->compr_config.codec) {
3953 ret = -ENOMEM;
3954 goto error_open;
3955 }
3956
vivek mehta0ea887a2015-08-26 14:01:20 -07003957 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303958 out->stream.pause = out_pause;
3959 out->stream.flush = out_flush;
3960 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003961 out->usecase = get_offload_usecase(adev, true);
3962 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003963 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003964 out->stream.set_callback = out_set_callback;
3965 out->stream.pause = out_pause;
3966 out->stream.resume = out_resume;
3967 out->stream.drain = out_drain;
3968 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003969 out->usecase = get_offload_usecase(adev, false);
3970 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003971 }
vivek mehta446c3962015-09-14 10:57:35 -07003972
3973 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003974 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3975 config->format == 0 && config->sample_rate == 0 &&
3976 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003977 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003978 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3979 } else {
3980 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3981 ret = -EEXIST;
3982 goto error_open;
3983 }
vivek mehta446c3962015-09-14 10:57:35 -07003984 }
3985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 if (config->offload_info.channel_mask)
3987 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003988 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003989 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003990 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003991 } else {
3992 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3993 ret = -EINVAL;
3994 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003995 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003996
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003997 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003998 out->sample_rate = config->offload_info.sample_rate;
3999
Mingming Yin3ee55c62014-08-04 14:23:35 -07004000 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004001
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304002 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4003 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4004 audio_extn_dolby_send_ddp_endp_params(adev);
4005 audio_extn_dolby_set_dmid(adev);
4006 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004007
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004008 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004009 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004010 out->compr_config.codec->bit_rate =
4011 config->offload_info.bit_rate;
4012 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304013 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004014 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304015 /* Update bit width only for non passthrough usecases.
4016 * For passthrough usecases, the output will always be opened @16 bit
4017 */
4018 if (!audio_extn_passthru_is_passthrough_stream(out))
4019 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004020 /*TODO: Do we need to change it for passthrough */
4021 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004022
Manish Dewangana6fc5442015-08-24 20:30:31 +05304023 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4024 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304025 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304026 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304027 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4028 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304029
4030 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4031 AUDIO_FORMAT_PCM) {
4032
4033 /*Based on platform support, configure appropriate alsa format for corresponding
4034 *hal input format.
4035 */
4036 out->compr_config.codec->format = hal_format_to_alsa(
4037 config->offload_info.format);
4038
Ashish Jain83a6cc22016-06-28 14:34:17 +05304039 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304040 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304041 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304042
4043 /*for direct PCM playback populate bit_width based on selected alsa format as
4044 *hal input format and alsa format might differ based on platform support.
4045 */
4046 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304047 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304048
4049 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4050
4051 /* Check if alsa session is configured with the same format as HAL input format,
4052 * if not then derive correct fragment size needed to accomodate the
4053 * conversion of HAL input format to alsa format.
4054 */
4055 audio_extn_utils_update_direct_pcm_fragment_size(out);
4056
4057 /*if hal input and output fragment size is different this indicates HAL input format is
4058 *not same as the alsa format
4059 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304060 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304061 /*Allocate a buffer to convert input data to the alsa configured format.
4062 *size of convert buffer is equal to the size required to hold one fragment size
4063 *worth of pcm data, this is because flinger does not write more than fragment_size
4064 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304065 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4066 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304067 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4068 ret = -ENOMEM;
4069 goto error_open;
4070 }
4071 }
4072 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4073 out->compr_config.fragment_size =
4074 audio_extn_passthru_get_buffer_size(&config->offload_info);
4075 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4076 } else {
4077 out->compr_config.fragment_size =
4078 platform_get_compress_offload_buffer_size(&config->offload_info);
4079 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4080 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004081
Amit Shekhar6f461b12014-08-01 14:52:58 -07004082 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304083 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004084
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304085 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4086 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4087 }
4088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004089 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4090 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004091
Alexy Josephaa54c872014-12-03 02:46:47 -08004092
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004093 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304094 out->send_next_track_params = false;
4095 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004096 out->offload_state = OFFLOAD_STATE_IDLE;
4097 out->playback_started = 0;
4098
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004099 audio_extn_dts_create_state_notifier_node(out->usecase);
4100
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4102 __func__, config->offload_info.version,
4103 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304104
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304105 /* Check if DSD audio format is supported in codec
4106 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304107 */
4108
4109 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304110 (!platform_check_codec_dsd_support(adev->platform) ||
4111 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304112 ret = -EINVAL;
4113 goto error_open;
4114 }
4115
Ashish Jain5106d362016-05-11 19:23:33 +05304116 /* Disable gapless if any of the following is true
4117 * passthrough playback
4118 * AV playback
4119 * Direct PCM playback
4120 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304121 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304122 (config->format == AUDIO_FORMAT_DSD) ||
4123 config->offload_info.has_video ||
4124 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304125 check_and_set_gapless_mode(adev, false);
4126 } else
4127 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004128
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304129 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004130 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4131 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304132 if (config->format == AUDIO_FORMAT_DSD) {
4133 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4134 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4135 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004136
4137 create_offload_callback_thread(out);
4138
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004139 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304140 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004141 if (ret != 0) {
4142 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4143 __func__, ret);
4144 goto error_open;
4145 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004146 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4147 if (config->sample_rate == 0)
4148 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4149 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4150 config->sample_rate != 8000) {
4151 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4152 ret = -EINVAL;
4153 goto error_open;
4154 }
4155 out->sample_rate = config->sample_rate;
4156 out->config.rate = config->sample_rate;
4157 if (config->format == AUDIO_FORMAT_DEFAULT)
4158 config->format = AUDIO_FORMAT_PCM_16_BIT;
4159 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4160 config->format = AUDIO_FORMAT_PCM_16_BIT;
4161 ret = -EINVAL;
4162 goto error_open;
4163 }
4164 out->format = config->format;
4165 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4166 out->config = pcm_config_afe_proxy_playback;
4167 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004168 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304169 unsigned int channels = 0;
4170 /*Update config params to default if not set by the caller*/
4171 if (config->sample_rate == 0)
4172 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4173 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4174 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4175 if (config->format == AUDIO_FORMAT_DEFAULT)
4176 config->format = AUDIO_FORMAT_PCM_16_BIT;
4177
4178 channels = audio_channel_count_from_out_mask(out->channel_mask);
4179
Ashish Jain83a6cc22016-06-28 14:34:17 +05304180 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4181 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004182 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4183 out->flags);
4184 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304185 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4186 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4187 out->config = pcm_config_low_latency;
4188 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4189 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4190 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304191 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4192 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4193 if (out->config.period_size <= 0) {
4194 ALOGE("Invalid configuration period size is not valid");
4195 ret = -EINVAL;
4196 goto error_open;
4197 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304198 } else {
4199 /* primary path is the default path selected if no other outputs are available/suitable */
4200 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4201 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4202 }
4203 out->hal_ip_format = format = out->format;
4204 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4205 out->hal_op_format = pcm_format_to_hal(out->config.format);
4206 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4207 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004208 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304209 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304210 if (out->hal_ip_format != out->hal_op_format) {
4211 uint32_t buffer_size = out->config.period_size *
4212 format_to_bitwidth_table[out->hal_op_format] *
4213 out->config.channels;
4214 out->convert_buffer = calloc(1, buffer_size);
4215 if (out->convert_buffer == NULL){
4216 ALOGE("Allocation failed for convert buffer for size %d",
4217 out->compr_config.fragment_size);
4218 ret = -ENOMEM;
4219 goto error_open;
4220 }
4221 ALOGD("Convert buffer allocated of size %d", buffer_size);
4222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 }
4224
Ashish Jain83a6cc22016-06-28 14:34:17 +05304225 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4226 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4227
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004228 /* TODO remove this hardcoding and check why width is zero*/
4229 if (out->bit_width == 0)
4230 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304231 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004232 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304233 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304234 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304235 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004236 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4237 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4238 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004239 if(adev->primary_output == NULL)
4240 adev->primary_output = out;
4241 else {
4242 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004243 ret = -EEXIST;
4244 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004245 }
4246 }
4247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 /* Check if this usecase is already existing */
4249 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004250 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4251 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004254 ret = -EEXIST;
4255 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 }
4257 pthread_mutex_unlock(&adev->lock);
4258
4259 out->stream.common.get_sample_rate = out_get_sample_rate;
4260 out->stream.common.set_sample_rate = out_set_sample_rate;
4261 out->stream.common.get_buffer_size = out_get_buffer_size;
4262 out->stream.common.get_channels = out_get_channels;
4263 out->stream.common.get_format = out_get_format;
4264 out->stream.common.set_format = out_set_format;
4265 out->stream.common.standby = out_standby;
4266 out->stream.common.dump = out_dump;
4267 out->stream.common.set_parameters = out_set_parameters;
4268 out->stream.common.get_parameters = out_get_parameters;
4269 out->stream.common.add_audio_effect = out_add_audio_effect;
4270 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4271 out->stream.get_latency = out_get_latency;
4272 out->stream.set_volume = out_set_volume;
4273 out->stream.write = out_write;
4274 out->stream.get_render_position = out_get_render_position;
4275 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004276 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004278 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004279 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004280 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004281 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282
4283 config->format = out->stream.common.get_format(&out->stream.common);
4284 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4285 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4286
4287 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304288 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004289 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004290
4291 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4292 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4293 popcount(out->channel_mask), out->playback_started);
4294
Eric Laurent994a6932013-07-17 11:51:42 -07004295 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004297
4298error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304299 if (out->convert_buffer)
4300 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004301 free(out);
4302 *stream_out = NULL;
4303 ALOGD("%s: exit: ret %d", __func__, ret);
4304 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004305}
4306
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304307void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308 struct audio_stream_out *stream)
4309{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004310 struct stream_out *out = (struct stream_out *)stream;
4311 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004312 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004313
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304314 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4315
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004316 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304317 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004318 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304319 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004320 if(ret != 0)
4321 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4322 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004323 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004324 out_standby(&stream->common);
4325
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004326 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004327 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004328 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004329 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004330 if (out->compr_config.codec != NULL)
4331 free(out->compr_config.codec);
4332 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004333
Ashish Jain83a6cc22016-06-28 14:34:17 +05304334 if (out->convert_buffer != NULL) {
4335 free(out->convert_buffer);
4336 out->convert_buffer = NULL;
4337 }
4338
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004339 if (adev->voice_tx_output == out)
4340 adev->voice_tx_output = NULL;
4341
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304342 if (adev->primary_output == out)
4343 adev->primary_output = NULL;
4344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345 pthread_cond_destroy(&out->cond);
4346 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004348 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349}
4350
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004351static void close_compress_sessions(struct audio_device *adev)
4352{
Mingming Yin7b762e72015-03-04 13:47:32 -08004353 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304354 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004355 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004356 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304357
4358 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004359 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304360 if (is_offload_usecase(usecase->id)) {
4361 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004362 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4363 out = usecase->stream.out;
4364 pthread_mutex_unlock(&adev->lock);
4365 out_standby(&out->stream.common);
4366 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004367 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004368 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304369 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004370 }
4371 pthread_mutex_unlock(&adev->lock);
4372}
4373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4375{
4376 struct audio_device *adev = (struct audio_device *)dev;
4377 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004379 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004380 int ret;
4381 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004383 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304386 if (!parms)
4387 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004388 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4389 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304390 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304391 if (strstr(snd_card_status, "OFFLINE")) {
4392 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304393 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004394 //close compress sessions on OFFLINE status
4395 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304396 } else if (strstr(snd_card_status, "ONLINE")) {
4397 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304398 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004399 //send dts hpx license if enabled
4400 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304401 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304402 }
4403
4404 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004405 status = voice_set_parameters(adev, parms);
4406 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004407 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004409 status = platform_set_parameters(adev->platform, parms);
4410 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004411 goto done;
4412
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004413 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4414 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004415 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4417 adev->bluetooth_nrec = true;
4418 else
4419 adev->bluetooth_nrec = false;
4420 }
4421
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004422 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4423 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4425 adev->screen_off = false;
4426 else
4427 adev->screen_off = true;
4428 }
4429
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004430 ret = str_parms_get_int(parms, "rotation", &val);
4431 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004432 bool reverse_speakers = false;
4433 switch(val) {
4434 // FIXME: note that the code below assumes that the speakers are in the correct placement
4435 // relative to the user when the device is rotated 90deg from its default rotation. This
4436 // assumption is device-specific, not platform-specific like this code.
4437 case 270:
4438 reverse_speakers = true;
4439 break;
4440 case 0:
4441 case 90:
4442 case 180:
4443 break;
4444 default:
4445 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004446 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004447 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004448 if (status == 0) {
4449 if (adev->speaker_lr_swap != reverse_speakers) {
4450 adev->speaker_lr_swap = reverse_speakers;
4451 // only update the selected device if there is active pcm playback
4452 struct audio_usecase *usecase;
4453 struct listnode *node;
4454 list_for_each(node, &adev->usecase_list) {
4455 usecase = node_to_item(node, struct audio_usecase, list);
4456 if (usecase->type == PCM_PLAYBACK) {
4457 select_devices(adev, usecase->id);
4458 break;
4459 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004460 }
4461 }
4462 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004463 }
4464
Mingming Yin514a8bc2014-07-29 15:22:21 -07004465 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4466 if (ret >= 0) {
4467 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4468 adev->bt_wb_speech_enabled = true;
4469 else
4470 adev->bt_wb_speech_enabled = false;
4471 }
4472
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004473 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4474 if (ret >= 0) {
4475 val = atoi(value);
4476 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004477 ALOGV("cache new ext disp type and edid");
4478 ret = platform_get_ext_disp_type(adev->platform);
4479 if (ret < 0) {
4480 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004481 status = ret;
4482 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004483 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004484 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004485 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004486 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004487 /*
4488 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4489 * Per AudioPolicyManager, USB device is higher priority than WFD.
4490 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4491 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4492 * starting voice call on USB
4493 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004494 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4495 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004496 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4497 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004498 }
vivek mehta344576a2016-04-12 18:56:03 -07004499 ALOGV("detected USB connect .. disable proxy");
4500 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004501 }
4502 }
4503
4504 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4505 if (ret >= 0) {
4506 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004507 /*
4508 * The HDMI / Displayport disconnect handling has been moved to
4509 * audio extension to ensure that its parameters are not
4510 * invalidated prior to updating sysfs of the disconnect event
4511 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4512 */
4513 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004514 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004515 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4516 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304517 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4518 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004519 }
vivek mehta344576a2016-04-12 18:56:03 -07004520 ALOGV("detected USB disconnect .. enable proxy");
4521 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004522 }
4523 }
4524
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304525 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4526 if (ret >= 0) {
4527 struct audio_usecase *usecase;
4528 struct listnode *node;
4529 list_for_each(node, &adev->usecase_list) {
4530 usecase = node_to_item(node, struct audio_usecase, list);
4531 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004532 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304533 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304534 lock_output_stream(usecase->stream.out);
4535 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304536 //force device switch to re configure encoder
4537 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304538 audio_extn_a2dp_set_handoff_mode(false);
4539 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304540 break;
4541 }
4542 }
4543 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304544 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004545done:
4546 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004547 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304548error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004549 ALOGV("%s: exit with code(%d)", __func__, status);
4550 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551}
4552
4553static char* adev_get_parameters(const struct audio_hw_device *dev,
4554 const char *keys)
4555{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004556 struct audio_device *adev = (struct audio_device *)dev;
4557 struct str_parms *reply = str_parms_create();
4558 struct str_parms *query = str_parms_create_str(keys);
4559 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304560 char value[256] = {0};
4561 int ret = 0;
4562
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004563 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004564 if (reply) {
4565 str_parms_destroy(reply);
4566 }
4567 if (query) {
4568 str_parms_destroy(query);
4569 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004570 ALOGE("adev_get_parameters: failed to create query or reply");
4571 return NULL;
4572 }
4573
Naresh Tannirud7205b62014-06-20 02:54:48 +05304574 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4575 sizeof(value));
4576 if (ret >=0) {
4577 int val = 1;
4578 pthread_mutex_lock(&adev->snd_card_status.lock);
4579 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4580 val = 0;
4581 pthread_mutex_unlock(&adev->snd_card_status.lock);
4582 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4583 goto exit;
4584 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004585
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004586 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004587 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004588 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004589 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304590 pthread_mutex_unlock(&adev->lock);
4591
Naresh Tannirud7205b62014-06-20 02:54:48 +05304592exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004593 str = str_parms_to_str(reply);
4594 str_parms_destroy(query);
4595 str_parms_destroy(reply);
4596
4597 ALOGV("%s: exit: returns - %s", __func__, str);
4598 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599}
4600
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004601static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602{
4603 return 0;
4604}
4605
4606static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4607{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004608 int ret;
4609 struct audio_device *adev = (struct audio_device *)dev;
4610 pthread_mutex_lock(&adev->lock);
4611 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004612 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004613 pthread_mutex_unlock(&adev->lock);
4614 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615}
4616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004617static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4618 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004619{
4620 return -ENOSYS;
4621}
4622
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004623static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4624 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625{
4626 return -ENOSYS;
4627}
4628
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004629static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4630 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631{
4632 return -ENOSYS;
4633}
4634
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004635static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4636 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637{
4638 return -ENOSYS;
4639}
4640
4641static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4642{
4643 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 pthread_mutex_lock(&adev->lock);
4646 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004647 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004649 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004650 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004651 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004652 adev->current_call_output = NULL;
4653 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 }
4655 pthread_mutex_unlock(&adev->lock);
4656 return 0;
4657}
4658
4659static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4660{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004661 int ret;
4662
4663 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004664 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004665 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4666 pthread_mutex_unlock(&adev->lock);
4667
4668 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669}
4670
4671static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4672{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004673 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 return 0;
4675}
4676
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004677static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 const struct audio_config *config)
4679{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004680 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004682 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4683 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684}
4685
4686static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004687 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688 audio_devices_t devices,
4689 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004690 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304691 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004692 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004693 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694{
4695 struct audio_device *adev = (struct audio_device *)dev;
4696 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004697 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004698 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004699 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304700 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304703 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4704 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304706 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
4708 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004709
4710 if (!in) {
4711 ALOGE("failed to allocate input stream");
4712 return -ENOMEM;
4713 }
4714
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304715 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304716 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4717 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004718 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004719 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721 in->stream.common.get_sample_rate = in_get_sample_rate;
4722 in->stream.common.set_sample_rate = in_set_sample_rate;
4723 in->stream.common.get_buffer_size = in_get_buffer_size;
4724 in->stream.common.get_channels = in_get_channels;
4725 in->stream.common.get_format = in_get_format;
4726 in->stream.common.set_format = in_set_format;
4727 in->stream.common.standby = in_standby;
4728 in->stream.common.dump = in_dump;
4729 in->stream.common.set_parameters = in_set_parameters;
4730 in->stream.common.get_parameters = in_get_parameters;
4731 in->stream.common.add_audio_effect = in_add_audio_effect;
4732 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4733 in->stream.set_gain = in_set_gain;
4734 in->stream.read = in_read;
4735 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4736
4737 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004738 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 in->standby = 1;
4741 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004742 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004743 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304745 in->usecase = USECASE_AUDIO_RECORD;
4746 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4747 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4748 is_low_latency = true;
4749#if LOW_LATENCY_CAPTURE_USE_CASE
4750 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4751#endif
4752 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4753 }
4754
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004755 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004756 if (in->realtime) {
4757 in->config = pcm_config_audio_capture_rt;
4758 in->sample_rate = in->config.rate;
4759 in->af_period_multiplier = af_period_multiplier;
4760 } else {
4761 in->config = pcm_config_audio_capture;
4762 in->config.rate = config->sample_rate;
4763 in->sample_rate = config->sample_rate;
4764 in->af_period_multiplier = 1;
4765 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304766 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304768 /* restrict 24 bit capture for unprocessed source only
4769 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4770 */
4771 if (config->format == AUDIO_FORMAT_DEFAULT) {
4772 config->format = AUDIO_FORMAT_PCM_16_BIT;
4773 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4774 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4775 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4776 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4777 bool ret_error = false;
4778 in->bit_width = 24;
4779 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4780 from HAL is 24_packed and 8_24
4781 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4782 24_packed return error indicating supported format is 24_packed
4783 *> In case of any other source requesting 24 bit or float return error
4784 indicating format supported is 16 bit only.
4785
4786 on error flinger will retry with supported format passed
4787 */
4788 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4789 (source != AUDIO_SOURCE_CAMCORDER)) {
4790 config->format = AUDIO_FORMAT_PCM_16_BIT;
4791 if (config->sample_rate > 48000)
4792 config->sample_rate = 48000;
4793 ret_error = true;
4794 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4795 in->config.format = PCM_FORMAT_S24_3LE;
4796 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4797 in->config.format = PCM_FORMAT_S24_LE;
4798 } else {
4799 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4800 ret_error = true;
4801 }
4802
4803 if (ret_error) {
4804 ret = -EINVAL;
4805 goto err_open;
4806 }
4807 }
4808
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304809 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304810 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4811 (adev->mode != AUDIO_MODE_IN_CALL)) {
4812 ret = -EINVAL;
4813 goto err_open;
4814 }
4815
4816 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4817 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004818 if (config->sample_rate == 0)
4819 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4820 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4821 config->sample_rate != 8000) {
4822 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4823 ret = -EINVAL;
4824 goto err_open;
4825 }
4826 if (config->format == AUDIO_FORMAT_DEFAULT)
4827 config->format = AUDIO_FORMAT_PCM_16_BIT;
4828 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4829 config->format = AUDIO_FORMAT_PCM_16_BIT;
4830 ret = -EINVAL;
4831 goto err_open;
4832 }
4833
4834 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4835 in->config = pcm_config_afe_proxy_record;
4836 in->config.channels = channel_count;
4837 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304838 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304839 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4840 in, config, &channel_mask_updated)) {
4841 if (channel_mask_updated == true) {
4842 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4843 __func__, config->channel_mask);
4844 ret = -EINVAL;
4845 goto err_open;
4846 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304847 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004848 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004849 audio_extn_compr_cap_format_supported(config->format) &&
4850 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004851 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304852 } else if (audio_extn_cin_applicable_stream(in)) {
4853 ret = audio_extn_cin_configure_input_stream(in);
4854 if (ret)
4855 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004856 } else {
4857 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004858 if (!in->realtime) {
4859 in->format = config->format;
4860 frame_size = audio_stream_in_frame_size(&in->stream);
4861 buffer_size = get_input_buffer_size(config->sample_rate,
4862 config->format,
4863 channel_count,
4864 is_low_latency);
4865 in->config.period_size = buffer_size / frame_size;
4866 }
4867
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004868 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004869 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004870 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004871 (in->config.rate == 8000 || in->config.rate == 16000 ||
4872 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004873 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4874 voice_extn_compress_voip_open_input_stream(in);
4875 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304878 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4879 &adev->streams_input_cfg_list,
4880 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304881 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304882
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004883 /* This stream could be for sound trigger lab,
4884 get sound trigger pcm if present */
4885 audio_extn_sound_trigger_check_and_get_session(in);
4886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004889 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890
4891err_open:
4892 free(in);
4893 *stream_in = NULL;
4894 return ret;
4895}
4896
4897static void adev_close_input_stream(struct audio_hw_device *dev,
4898 struct audio_stream_in *stream)
4899{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004900 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004901 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004902 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304903
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304904 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004905
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304906 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004907 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304908
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004909 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304910 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004911 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304912 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004913 if (ret != 0)
4914 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4915 __func__, ret);
4916 } else
4917 in_standby(&stream->common);
4918
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004919 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004920 audio_extn_ssr_deinit();
4921 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304923 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004924 audio_extn_compr_cap_format_supported(in->config.format))
4925 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304926
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304927 if (audio_extn_cin_attached_usecase(in->usecase))
4928 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004929
Mingming Yinfd7607b2016-01-22 12:48:44 -08004930 if (in->is_st_session) {
4931 ALOGV("%s: sound trigger pcm stop lab", __func__);
4932 audio_extn_sound_trigger_stop_lab(in);
4933 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004934 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935 return;
4936}
4937
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004938static int adev_dump(const audio_hw_device_t *device __unused,
4939 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940{
4941 return 0;
4942}
4943
4944static int adev_close(hw_device_t *device)
4945{
4946 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004947
4948 if (!adev)
4949 return 0;
4950
4951 pthread_mutex_lock(&adev_init_lock);
4952
4953 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004954 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004955 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304956 audio_extn_utils_release_streams_cfg_lists(
4957 &adev->streams_output_cfg_list,
4958 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304959 if (audio_extn_qaf_is_enabled())
4960 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004961 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004962 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004963 free(adev->snd_dev_ref_cnt);
4964 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004965 if (adev->adm_deinit)
4966 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304967 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004968 free(device);
4969 adev = NULL;
4970 }
4971 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973 return 0;
4974}
4975
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004976/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4977 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4978 * just that it _might_ work.
4979 */
4980static int period_size_is_plausible_for_low_latency(int period_size)
4981{
4982 switch (period_size) {
4983 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004984 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004985 case 240:
4986 case 320:
4987 case 480:
4988 return 1;
4989 default:
4990 return 0;
4991 }
4992}
4993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994static int adev_open(const hw_module_t *module, const char *name,
4995 hw_device_t **device)
4996{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304997 int ret;
4998
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004999 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5001
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005002 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005003 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005004 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005005 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005006 ALOGD("%s: returning existing instance of adev", __func__);
5007 ALOGD("%s: exit", __func__);
5008 pthread_mutex_unlock(&adev_init_lock);
5009 return 0;
5010 }
5011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012 adev = calloc(1, sizeof(struct audio_device));
5013
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005014 if (!adev) {
5015 pthread_mutex_unlock(&adev_init_lock);
5016 return -ENOMEM;
5017 }
5018
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005019 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5022 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5023 adev->device.common.module = (struct hw_module_t *)module;
5024 adev->device.common.close = adev_close;
5025
5026 adev->device.init_check = adev_init_check;
5027 adev->device.set_voice_volume = adev_set_voice_volume;
5028 adev->device.set_master_volume = adev_set_master_volume;
5029 adev->device.get_master_volume = adev_get_master_volume;
5030 adev->device.set_master_mute = adev_set_master_mute;
5031 adev->device.get_master_mute = adev_get_master_mute;
5032 adev->device.set_mode = adev_set_mode;
5033 adev->device.set_mic_mute = adev_set_mic_mute;
5034 adev->device.get_mic_mute = adev_get_mic_mute;
5035 adev->device.set_parameters = adev_set_parameters;
5036 adev->device.get_parameters = adev_get_parameters;
5037 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5038 adev->device.open_output_stream = adev_open_output_stream;
5039 adev->device.close_output_stream = adev_close_output_stream;
5040 adev->device.open_input_stream = adev_open_input_stream;
5041 adev->device.close_input_stream = adev_close_input_stream;
5042 adev->device.dump = adev_dump;
5043
5044 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005046 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005047 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005048 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005050 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005051 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005052 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005053 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005054 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005055 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005056 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005057 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305058 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305059 adev->perf_lock_opts[0] = 0x101;
5060 adev->perf_lock_opts[1] = 0x20E;
5061 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305062
5063 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5064 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005066 adev->platform = platform_init(adev);
5067 if (!adev->platform) {
5068 free(adev->snd_dev_ref_cnt);
5069 free(adev);
5070 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5071 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005072 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305073 pthread_mutex_destroy(&adev->lock);
5074 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005075 return -EINVAL;
5076 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005077
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305078 if (audio_extn_qaf_is_enabled()) {
5079 ret = audio_extn_qaf_init(adev);
5080 if (ret < 0) {
5081 free(adev);
5082 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5083 *device = NULL;
5084 pthread_mutex_unlock(&adev_init_lock);
5085 pthread_mutex_destroy(&adev->lock);
5086 return ret;
5087 }
5088
5089 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5090 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5091 }
5092
Naresh Tanniru4c630392014-05-12 01:05:52 +05305093 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5094
Eric Laurentc4aef752013-09-12 17:45:53 -07005095 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5096 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5097 if (adev->visualizer_lib == NULL) {
5098 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5099 } else {
5100 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5101 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005102 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005103 "visualizer_hal_start_output");
5104 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005105 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005106 "visualizer_hal_stop_output");
5107 }
5108 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305109 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005110 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005111 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005112 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005113
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005114 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5115 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5116 if (adev->offload_effects_lib == NULL) {
5117 ALOGE("%s: DLOPEN failed for %s", __func__,
5118 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5119 } else {
5120 ALOGV("%s: DLOPEN successful for %s", __func__,
5121 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5122 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305123 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005124 "offload_effects_bundle_hal_start_output");
5125 adev->offload_effects_stop_output =
5126 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5127 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005128 adev->offload_effects_set_hpx_state =
5129 (int (*)(bool))dlsym(adev->offload_effects_lib,
5130 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305131 adev->offload_effects_get_parameters =
5132 (void (*)(struct str_parms *, struct str_parms *))
5133 dlsym(adev->offload_effects_lib,
5134 "offload_effects_bundle_get_parameters");
5135 adev->offload_effects_set_parameters =
5136 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5137 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005138 }
5139 }
5140
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005141 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5142 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5143 if (adev->adm_lib == NULL) {
5144 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5145 } else {
5146 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5147 adev->adm_init = (adm_init_t)
5148 dlsym(adev->adm_lib, "adm_init");
5149 adev->adm_deinit = (adm_deinit_t)
5150 dlsym(adev->adm_lib, "adm_deinit");
5151 adev->adm_register_input_stream = (adm_register_input_stream_t)
5152 dlsym(adev->adm_lib, "adm_register_input_stream");
5153 adev->adm_register_output_stream = (adm_register_output_stream_t)
5154 dlsym(adev->adm_lib, "adm_register_output_stream");
5155 adev->adm_deregister_stream = (adm_deregister_stream_t)
5156 dlsym(adev->adm_lib, "adm_deregister_stream");
5157 adev->adm_request_focus = (adm_request_focus_t)
5158 dlsym(adev->adm_lib, "adm_request_focus");
5159 adev->adm_abandon_focus = (adm_abandon_focus_t)
5160 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005161 adev->adm_set_config = (adm_set_config_t)
5162 dlsym(adev->adm_lib, "adm_set_config");
5163 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5164 dlsym(adev->adm_lib, "adm_request_focus_v2");
5165 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5166 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5167 adev->adm_on_routing_change = (adm_on_routing_change_t)
5168 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005169 }
5170 }
5171
Mingming Yin514a8bc2014-07-29 15:22:21 -07005172 adev->bt_wb_speech_enabled = false;
5173
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005174 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005175 *device = &adev->device.common;
5176
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305177 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5178 &adev->streams_output_cfg_list,
5179 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005180
Kiran Kandi910e1862013-10-29 13:29:42 -07005181 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005182
5183 char value[PROPERTY_VALUE_MAX];
5184 int trial;
5185 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5186 trial = atoi(value);
5187 if (period_size_is_plausible_for_low_latency(trial)) {
5188 pcm_config_low_latency.period_size = trial;
5189 pcm_config_low_latency.start_threshold = trial / 4;
5190 pcm_config_low_latency.avail_min = trial / 4;
5191 configured_low_latency_capture_period_size = trial;
5192 }
5193 }
5194 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5195 trial = atoi(value);
5196 if (period_size_is_plausible_for_low_latency(trial)) {
5197 configured_low_latency_capture_period_size = trial;
5198 }
5199 }
5200
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005201 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5202 af_period_multiplier = atoi(value);
5203 if (af_period_multiplier < 0)
5204 af_period_multiplier = 2;
5205 else if (af_period_multiplier > 4)
5206 af_period_multiplier = 4;
5207
5208 ALOGV("new period_multiplier = %d", af_period_multiplier);
5209 }
5210
vivek mehta446c3962015-09-14 10:57:35 -07005211 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005212 pthread_mutex_unlock(&adev_init_lock);
5213
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005214 if (adev->adm_init)
5215 adev->adm_data = adev->adm_init();
5216
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305217 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305218 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005219 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220 return 0;
5221}
5222
5223static struct hw_module_methods_t hal_module_methods = {
5224 .open = adev_open,
5225};
5226
5227struct audio_module HAL_MODULE_INFO_SYM = {
5228 .common = {
5229 .tag = HARDWARE_MODULE_TAG,
5230 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5231 .hal_api_version = HARDWARE_HAL_API_VERSION,
5232 .id = AUDIO_HARDWARE_MODULE_ID,
5233 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005234 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005235 .methods = &hal_module_methods,
5236 },
5237};