blob: e60ce6e4fe3b317a468eadf6060a57cb7d276fce [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 ||
524 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800525 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700526
527 return false;
528}
529
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700530static inline bool is_mmap_usecase(audio_usecase_t uc_id)
531{
532 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
533 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
534}
535
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530536int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530537{
538 int snd_scard_state;
539
540 if (!adev)
541 return SND_CARD_STATE_OFFLINE;
542
543 pthread_mutex_lock(&adev->snd_card_status.lock);
544 snd_scard_state = adev->snd_card_status.state;
545 pthread_mutex_unlock(&adev->snd_card_status.lock);
546
547 return snd_scard_state;
548}
549
550static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
551{
552 if (!adev)
553 return -ENOSYS;
554
555 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700556 if (adev->snd_card_status.state != snd_scard_state) {
557 adev->snd_card_status.state = snd_scard_state;
558 platform_snd_card_update(adev->platform, snd_scard_state);
559 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530560 pthread_mutex_unlock(&adev->snd_card_status.lock);
561
562 return 0;
563}
564
Avinash Vaish71a8b972014-07-24 15:36:33 +0530565static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
566 struct audio_usecase *uc_info)
567{
568 struct listnode *node;
569 struct audio_usecase *usecase;
570
571 if (uc_info == NULL)
572 return -EINVAL;
573
574 /* Re-route all voice usecases on the shared backend other than the
575 specified usecase to new snd devices */
576 list_for_each(node, &adev->usecase_list) {
577 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800578 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530579 enable_audio_route(adev, usecase);
580 }
581 return 0;
582}
583
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530584static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530585{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530586 ALOGV("%s", __func__);
587 audio_route_apply_and_update_path(adev->audio_route,
588 "asrc-mode");
589 adev->asrc_mode_enabled = true;
590}
591
592static void disable_asrc_mode(struct audio_device *adev)
593{
594 ALOGV("%s", __func__);
595 audio_route_reset_and_update_path(adev->audio_route,
596 "asrc-mode");
597 adev->asrc_mode_enabled = false;
598}
599
600/*
601 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
602 * 44.1 or Native DSD backends are enabled for any of current use case.
603 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
604 * - Disable current mix path use case(Headphone backend) and re-enable it with
605 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
606 * e.g. Naitve DSD or Headphone 44.1 -> + 48
607 */
608static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
609{
610 ALOGV("%s snd device %d", __func__, snd_device);
611 int new_backend_idx = platform_get_backend_index(snd_device);
612
613 if (((new_backend_idx == HEADPHONE_BACKEND) ||
614 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
615 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
616 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530617 struct listnode *node = NULL;
618 struct audio_usecase *uc = NULL;
619 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530620 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530621
622 list_for_each(node, &adev->usecase_list) {
623 uc = node_to_item(node, struct audio_usecase, list);
624 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530625 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530626 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
627
628 if((new_backend_idx == HEADPHONE_BACKEND) &&
629 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
630 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530631 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
632 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530633 enable_asrc_mode(adev);
634 break;
635 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
636 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
637 (usecase_backend_idx == HEADPHONE_BACKEND)) {
638 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
639 __func__);
640 disable_audio_route(adev, uc);
641 disable_snd_device(adev, uc->out_snd_device);
642 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
643 if (new_backend_idx == DSD_NATIVE_BACKEND)
644 audio_route_apply_and_update_path(adev->audio_route,
645 "hph-true-highquality-mode");
646 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
647 (curr_out->bit_width >= 24))
648 audio_route_apply_and_update_path(adev->audio_route,
649 "hph-highquality-mode");
650 enable_asrc_mode(adev);
651 enable_snd_device(adev, uc->out_snd_device);
652 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530653 break;
654 }
655 }
656 }
657 }
658}
659
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700660int pcm_ioctl(struct pcm *pcm, int request, ...)
661{
662 va_list ap;
663 void * arg;
664 int pcm_fd = *(int*)pcm;
665
666 va_start(ap, request);
667 arg = va_arg(ap, void *);
668 va_end(ap);
669
670 return ioctl(pcm_fd, request, arg);
671}
672
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700673int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700674 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800675{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700677 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800678
679 if (usecase == NULL)
680 return -EINVAL;
681
682 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
683
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800684 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800686 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700687 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800688
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800689#ifdef DS1_DOLBY_DAP_ENABLED
690 audio_extn_dolby_set_dmid(adev);
691 audio_extn_dolby_set_endpoint(adev);
692#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700693 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700694 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530695 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700696 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530697 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800698 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700699 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700700 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700701 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800702 ALOGV("%s: exit", __func__);
703 return 0;
704}
705
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700706int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700707 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800708{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700710 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800711
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530712 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800713 return -EINVAL;
714
715 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700716 if (usecase->type == PCM_CAPTURE)
717 snd_device = usecase->in_snd_device;
718 else
719 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800720 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700721 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700722 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700723 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700724 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530725 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726 ALOGV("%s: exit", __func__);
727 return 0;
728}
729
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700730int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700731 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530733 int i, num_devices = 0;
734 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700735 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
736
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800737 if (snd_device < SND_DEVICE_MIN ||
738 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800739 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800740 return -EINVAL;
741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742
743 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700744
745 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
746 ALOGE("%s: Invalid sound device returned", __func__);
747 return -EINVAL;
748 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700750 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700751 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700752 return 0;
753 }
754
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530755
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700756 if (audio_extn_spkr_prot_is_enabled())
757 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700758
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800759 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
760 audio_extn_spkr_prot_is_enabled()) {
761 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700762 adev->snd_dev_ref_cnt[snd_device]--;
763 return -EINVAL;
764 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200765 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800766 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800767 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200768 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800769 return -EINVAL;
770 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700771 } else if (platform_split_snd_device(adev->platform,
772 snd_device,
773 &num_devices,
774 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530775 for (i = 0; i < num_devices; i++) {
776 enable_snd_device(adev, new_snd_devices[i]);
777 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800778 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700779 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530780
781 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
782 (audio_extn_a2dp_start_playback() < 0)) {
783 ALOGE(" fail to configure A2dp control path ");
784 return -EINVAL;
785 }
786
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700787 /* due to the possibility of calibration overwrite between listen
788 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700789 audio_extn_sound_trigger_update_device_status(snd_device,
790 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530791 audio_extn_listen_update_device_status(snd_device,
792 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700793 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700794 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700795 audio_extn_sound_trigger_update_device_status(snd_device,
796 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530797 audio_extn_listen_update_device_status(snd_device,
798 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700799 return -EINVAL;
800 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300801 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700802 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530803
804 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
805 !adev->native_playback_enabled &&
806 audio_is_true_native_stream_active(adev)) {
807 ALOGD("%s: %d: napb: enabling native mode in hardware",
808 __func__, __LINE__);
809 audio_route_apply_and_update_path(adev->audio_route,
810 "true-native-mode");
811 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530812 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814 return 0;
815}
816
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700817int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700818 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530820 int i, num_devices = 0;
821 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700822 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
823
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800824 if (snd_device < SND_DEVICE_MIN ||
825 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800826 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800827 return -EINVAL;
828 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
830 ALOGE("%s: device ref cnt is already 0", __func__);
831 return -EINVAL;
832 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700833
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700835
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700836 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
837 ALOGE("%s: Invalid sound device returned", __func__);
838 return -EINVAL;
839 }
840
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700842 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530843
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800844 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
845 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700846 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700847 } else if (platform_split_snd_device(adev->platform,
848 snd_device,
849 &num_devices,
850 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530851 for (i = 0; i < num_devices; i++) {
852 disable_snd_device(adev, new_snd_devices[i]);
853 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300854 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700855 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300856 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700857
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530858 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
859 audio_extn_a2dp_stop_playback();
860
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700861 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530862 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530863 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
864 adev->native_playback_enabled) {
865 ALOGD("%s: %d: napb: disabling native mode in hardware",
866 __func__, __LINE__);
867 audio_route_reset_and_update_path(adev->audio_route,
868 "true-native-mode");
869 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530870 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
871 adev->asrc_mode_enabled) {
872 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530873 disable_asrc_mode(adev);
874 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530875 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530876
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200877 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700878 audio_extn_sound_trigger_update_device_status(snd_device,
879 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530880 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800881 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800884 return 0;
885}
886
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700887/*
888 legend:
889 uc - existing usecase
890 new_uc - new usecase
891 d1, d11, d2 - SND_DEVICE enums
892 a1, a2 - corresponding ANDROID device enums
893 B1, B2 - backend strings
894
895case 1
896 uc->dev d1 (a1) B1
897 new_uc->dev d1 (a1), d2 (a2) B1, B2
898
899 resolution: disable and enable uc->dev on d1
900
901case 2
902 uc->dev d1 (a1) B1
903 new_uc->dev d11 (a1) B1
904
905 resolution: need to switch uc since d1 and d11 are related
906 (e.g. speaker and voice-speaker)
907 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
908
909case 3
910 uc->dev d1 (a1) B1
911 new_uc->dev d2 (a2) B2
912
913 resolution: no need to switch uc
914
915case 4
916 uc->dev d1 (a1) B1
917 new_uc->dev d2 (a2) B1
918
919 resolution: disable enable uc-dev on d2 since backends match
920 we cannot enable two streams on two different devices if they
921 share the same backend. e.g. if offload is on speaker device using
922 QUAD_MI2S backend and a low-latency stream is started on voice-handset
923 using the same backend, offload must also be switched to voice-handset.
924
925case 5
926 uc->dev d1 (a1) B1
927 new_uc->dev d1 (a1), d2 (a2) B1
928
929 resolution: disable enable uc-dev on d2 since backends match
930 we cannot enable two streams on two different devices if they
931 share the same backend.
932
933case 6
934 uc->dev d1 (a1) B1
935 new_uc->dev d2 (a1) B2
936
937 resolution: no need to switch
938
939case 7
940 uc->dev d1 (a1), d2 (a2) B1, B2
941 new_uc->dev d1 (a1) B1
942
943 resolution: no need to switch
944
945*/
946static snd_device_t derive_playback_snd_device(void * platform,
947 struct audio_usecase *uc,
948 struct audio_usecase *new_uc,
949 snd_device_t new_snd_device)
950{
951 audio_devices_t a1 = uc->stream.out->devices;
952 audio_devices_t a2 = new_uc->stream.out->devices;
953
954 snd_device_t d1 = uc->out_snd_device;
955 snd_device_t d2 = new_snd_device;
956
957 // Treat as a special case when a1 and a2 are not disjoint
958 if ((a1 != a2) && (a1 & a2)) {
959 snd_device_t d3[2];
960 int num_devices = 0;
961 int ret = platform_split_snd_device(platform,
962 popcount(a1) > 1 ? d1 : d2,
963 &num_devices,
964 d3);
965 if (ret < 0) {
966 if (ret != -ENOSYS) {
967 ALOGW("%s failed to split snd_device %d",
968 __func__,
969 popcount(a1) > 1 ? d1 : d2);
970 }
971 goto end;
972 }
973
974 // NB: case 7 is hypothetical and isn't a practical usecase yet.
975 // But if it does happen, we need to give priority to d2 if
976 // the combo devices active on the existing usecase share a backend.
977 // This is because we cannot have a usecase active on a combo device
978 // and a new usecase requests one device in this combo pair.
979 if (platform_check_backends_match(d3[0], d3[1])) {
980 return d2; // case 5
981 } else {
982 return d1; // case 1
983 }
984 } else {
985 if (platform_check_backends_match(d1, d2)) {
986 return d2; // case 2, 4
987 } else {
988 return d1; // case 6, 3
989 }
990 }
991
992end:
993 return d2; // return whatever was calculated before.
994}
995
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700996static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530997 struct audio_usecase *uc_info,
998 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999{
1000 struct listnode *node;
1001 struct audio_usecase *usecase;
1002 bool switch_device[AUDIO_USECASE_MAX];
1003 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001004 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301005 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 /*
1007 * This function is to make sure that all the usecases that are active on
1008 * the hardware codec backend are always routed to any one device that is
1009 * handled by the hardware codec.
1010 * For example, if low-latency and deep-buffer usecases are currently active
1011 * on speaker and out_set_parameters(headset) is received on low-latency
1012 * output, then we have to make sure deep-buffer is also switched to headset,
1013 * because of the limitation that both the devices cannot be enabled
1014 * at the same time as they share the same backend.
1015 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001016 /*
1017 * This call is to check if we need to force routing for a particular stream
1018 * If there is a backend configuration change for the device when a
1019 * new stream starts, then ADM needs to be closed and re-opened with the new
1020 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001021 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001022 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001023 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1024 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301025 /* For a2dp device reconfigure all active sessions
1026 * with new AFE encoder format based on a2dp state
1027 */
1028 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1029 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1030 audio_extn_a2dp_is_force_device_switch()) {
1031 force_routing = true;
1032 force_restart_session = true;
1033 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301034 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1035
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001037 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001038 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1040 switch_device[i] = false;
1041
1042 list_for_each(node, &adev->usecase_list) {
1043 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001044
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301045 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1046 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301047 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301048 platform_get_snd_device_name(usecase->out_snd_device),
1049 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001050 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301051 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001052 (derive_playback_snd_device(adev->platform,
1053 usecase, uc_info,
1054 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301055 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1056 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301057 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301058 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1059 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1060 ((force_restart_session) ||
1061 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301062
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301063 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1064 __func__, use_case_table[usecase->id],
1065 platform_get_snd_device_name(usecase->out_snd_device));
1066 disable_audio_route(adev, usecase);
1067 switch_device[usecase->id] = true;
1068 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069 }
1070 }
1071
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301072 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1073 num_uc_to_switch);
1074
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001075 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001076 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301078 /* Make sure the previous devices to be disabled first and then enable the
1079 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 list_for_each(node, &adev->usecase_list) {
1081 usecase = node_to_item(node, struct audio_usecase, list);
1082 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001083 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 }
1085 }
1086
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001087 list_for_each(node, &adev->usecase_list) {
1088 usecase = node_to_item(node, struct audio_usecase, list);
1089 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001090 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001091 }
1092 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 /* Re-route all the usecases on the shared backend other than the
1095 specified usecase to new snd devices */
1096 list_for_each(node, &adev->usecase_list) {
1097 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301098 /* Update the out_snd_device only before enabling the audio route */
1099 if (switch_device[usecase->id]) {
1100 usecase->out_snd_device = snd_device;
1101 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301102 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301103 use_case_table[usecase->id],
1104 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001105 /* Update voc calibration before enabling VoIP route */
1106 if (usecase->type == VOIP_CALL)
1107 status = platform_switch_voice_call_device_post(adev->platform,
1108 usecase->out_snd_device,
1109 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301110 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 }
1113 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 }
1115}
1116
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301117static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001118 struct audio_usecase *uc_info,
1119 snd_device_t snd_device)
1120{
1121 struct listnode *node;
1122 struct audio_usecase *usecase;
1123 bool switch_device[AUDIO_USECASE_MAX];
1124 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301125 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001126 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001127
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301128 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1129 snd_device);
1130 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301131
1132 /*
1133 * Make sure out devices is checked against out codec backend device and
1134 * also in devices against in codec backend. Checking out device against in
1135 * codec backend or vice versa causes issues.
1136 */
1137 if (uc_info->type == PCM_CAPTURE)
1138 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001139 /*
1140 * This function is to make sure that all the active capture usecases
1141 * are always routed to the same input sound device.
1142 * For example, if audio-record and voice-call usecases are currently
1143 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1144 * is received for voice call then we have to make sure that audio-record
1145 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1146 * because of the limitation that two devices cannot be enabled
1147 * at the same time if they share the same backend.
1148 */
1149 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1150 switch_device[i] = false;
1151
1152 list_for_each(node, &adev->usecase_list) {
1153 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301154 /*
1155 * TODO: Enhance below condition to handle BT sco/USB multi recording
1156 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001157 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001158 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301159 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301160 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301161 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001162 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001163 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001164 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1165 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001166 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001167 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168 switch_device[usecase->id] = true;
1169 num_uc_to_switch++;
1170 }
1171 }
1172
1173 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001174 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301176 /* Make sure the previous devices to be disabled first and then enable the
1177 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001178 list_for_each(node, &adev->usecase_list) {
1179 usecase = node_to_item(node, struct audio_usecase, list);
1180 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001181 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001182 }
1183 }
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
1187 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001188 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001189 }
1190 }
1191
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001192 /* Re-route all the usecases on the shared backend other than the
1193 specified usecase to new snd devices */
1194 list_for_each(node, &adev->usecase_list) {
1195 usecase = node_to_item(node, struct audio_usecase, list);
1196 /* Update the in_snd_device only before enabling the audio route */
1197 if (switch_device[usecase->id] ) {
1198 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001199 if (usecase->type != VOICE_CALL) {
1200 /* Update voc calibration before enabling VoIP route */
1201 if (usecase->type == VOIP_CALL)
1202 status = platform_switch_voice_call_device_post(adev->platform,
1203 usecase->out_snd_device,
1204 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301205 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001206 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001207 }
1208 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001209 }
1210}
1211
Mingming Yin3a941d42016-02-17 18:08:05 -08001212static void reset_hdmi_sink_caps(struct stream_out *out) {
1213 int i = 0;
1214
1215 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1216 out->supported_channel_masks[i] = 0;
1217 }
1218 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1219 out->supported_formats[i] = 0;
1220 }
1221 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1222 out->supported_sample_rates[i] = 0;
1223 }
1224}
1225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001227static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228{
Mingming Yin3a941d42016-02-17 18:08:05 -08001229 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001230 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231
Mingming Yin3a941d42016-02-17 18:08:05 -08001232 reset_hdmi_sink_caps(out);
1233
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001234 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001235 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001236 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001237 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001238 }
1239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001242 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001243 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001244 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1245 case 6:
1246 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1247 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1248 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1249 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1250 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1251 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 break;
1253 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001254 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001255 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256 break;
1257 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001258
1259 // check channel format caps
1260 i = 0;
1261 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1262 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1263 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1264 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1265 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1266 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1267 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1268 }
1269
1270 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1271 ALOGV(":%s HDMI supports DTS format", __func__);
1272 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1273 }
1274
1275 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1276 ALOGV(":%s HDMI supports DTS HD format", __func__);
1277 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1278 }
1279
1280
1281 // check sample rate caps
1282 i = 0;
1283 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1284 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1285 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1286 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1287 }
1288 }
1289
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001290 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291}
1292
Alexy Josephb1379942016-01-29 15:49:38 -08001293audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001294 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001295{
1296 struct audio_usecase *usecase;
1297 struct listnode *node;
1298
1299 list_for_each(node, &adev->usecase_list) {
1300 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001301 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001302 ALOGV("%s: usecase id %d", __func__, usecase->id);
1303 return usecase->id;
1304 }
1305 }
1306 return USECASE_INVALID;
1307}
1308
Alexy Josephb1379942016-01-29 15:49:38 -08001309struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001310 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001311{
1312 struct audio_usecase *usecase;
1313 struct listnode *node;
1314
1315 list_for_each(node, &adev->usecase_list) {
1316 usecase = node_to_item(node, struct audio_usecase, list);
1317 if (usecase->id == uc_id)
1318 return usecase;
1319 }
1320 return NULL;
1321}
1322
Dhananjay Kumard4833242016-10-06 22:09:12 +05301323struct stream_in *get_next_active_input(const struct audio_device *adev)
1324{
1325 struct audio_usecase *usecase;
1326 struct listnode *node;
1327
1328 list_for_each_reverse(node, &adev->usecase_list) {
1329 usecase = node_to_item(node, struct audio_usecase, list);
1330 if (usecase->type == PCM_CAPTURE)
1331 return usecase->stream.in;
1332 }
1333 return NULL;
1334}
1335
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301336/*
1337 * is a true native playback active
1338 */
1339bool audio_is_true_native_stream_active(struct audio_device *adev)
1340{
1341 bool active = false;
1342 int i = 0;
1343 struct listnode *node;
1344
1345 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1346 ALOGV("%s:napb: not in true mode or non hdphones device",
1347 __func__);
1348 active = false;
1349 goto exit;
1350 }
1351
1352 list_for_each(node, &adev->usecase_list) {
1353 struct audio_usecase *uc;
1354 uc = node_to_item(node, struct audio_usecase, list);
1355 struct stream_out *curr_out =
1356 (struct stream_out*) uc->stream.out;
1357
1358 if (curr_out && PCM_PLAYBACK == uc->type) {
1359 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1360 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1361 uc->id, curr_out->sample_rate,
1362 curr_out->bit_width,
1363 platform_get_snd_device_name(uc->out_snd_device));
1364
1365 if (is_offload_usecase(uc->id) &&
1366 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1367 active = true;
1368 ALOGD("%s:napb:native stream detected", __func__);
1369 }
1370 }
1371 }
1372exit:
1373 return active;
1374}
1375
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301376/*
1377 * if native DSD playback active
1378 */
1379bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1380{
1381 bool active = false;
1382 struct listnode *node = NULL;
1383 struct audio_usecase *uc = NULL;
1384 struct stream_out *curr_out = NULL;
1385
1386 list_for_each(node, &adev->usecase_list) {
1387 uc = node_to_item(node, struct audio_usecase, list);
1388 curr_out = (struct stream_out*) uc->stream.out;
1389
1390 if (curr_out && PCM_PLAYBACK == uc->type &&
1391 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1392 active = true;
1393 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301394 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301395 }
1396 }
1397 return active;
1398}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301399
1400static bool force_device_switch(struct audio_usecase *usecase)
1401{
1402 bool ret = false;
1403 bool is_it_true_mode = false;
1404
1405 if (is_offload_usecase(usecase->id) &&
1406 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001407 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1408 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1409 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301410 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1411 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1412 (!is_it_true_mode && adev->native_playback_enabled)){
1413 ret = true;
1414 ALOGD("napb: time to toggle native mode");
1415 }
1416 }
1417
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301418 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301419 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1420 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301421 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001422 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301423 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301424 ALOGD("Force a2dp device switch to update new encoder config");
1425 ret = true;
1426 }
1427
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301428 return ret;
1429}
1430
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001431int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001433 snd_device_t out_snd_device = SND_DEVICE_NONE;
1434 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 struct audio_usecase *usecase = NULL;
1436 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001437 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001438 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001439 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301442 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1443
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 usecase = get_usecase_from_list(adev, uc_id);
1445 if (usecase == NULL) {
1446 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1447 return -EINVAL;
1448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001450 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001451 (usecase->type == VOIP_CALL) ||
1452 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301453 if(usecase->stream.out == NULL) {
1454 ALOGE("%s: stream.out is NULL", __func__);
1455 return -EINVAL;
1456 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001457 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001458 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001459 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001460 usecase->devices = usecase->stream.out->devices;
1461 } else {
1462 /*
1463 * If the voice call is active, use the sound devices of voice call usecase
1464 * so that it would not result any device switch. All the usecases will
1465 * be switched to new device when select_devices() is called for voice call
1466 * usecase. This is to avoid switching devices for voice call when
1467 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001468 * choose voice call device only if the use case device is
1469 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001471 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001472 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001473 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001474 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1475 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301476 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1477 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001478 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001479 in_snd_device = vc_usecase->in_snd_device;
1480 out_snd_device = vc_usecase->out_snd_device;
1481 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001482 } else if (voice_extn_compress_voip_is_active(adev)) {
1483 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001484 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001485 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1486 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001487 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001488 in_snd_device = voip_usecase->in_snd_device;
1489 out_snd_device = voip_usecase->out_snd_device;
1490 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001491 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001492 hfp_ucid = audio_extn_hfp_get_usecase();
1493 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001494 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001495 in_snd_device = hfp_usecase->in_snd_device;
1496 out_snd_device = hfp_usecase->out_snd_device;
1497 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498 }
1499 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301500 if (usecase->stream.out == NULL) {
1501 ALOGE("%s: stream.out is NULL", __func__);
1502 return -EINVAL;
1503 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001504 usecase->devices = usecase->stream.out->devices;
1505 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001506 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001507 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001508 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001509 if (usecase->stream.out == adev->primary_output &&
1510 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001511 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001512 select_devices(adev, adev->active_input->usecase);
1513 }
1514 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301516 if (usecase->stream.in == NULL) {
1517 ALOGE("%s: stream.in is NULL", __func__);
1518 return -EINVAL;
1519 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 usecase->devices = usecase->stream.in->device;
1521 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001522 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001523 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001524 if (adev->active_input &&
1525 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301526 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1527 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1528 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001529 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001530 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001531 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1532 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001533 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001534 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 }
1537 }
1538
1539 if (out_snd_device == usecase->out_snd_device &&
1540 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301541
1542 if (!force_device_switch(usecase))
1543 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 }
1545
sangwoobc677242013-08-08 16:53:43 +09001546 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001547 out_snd_device, platform_get_snd_device_name(out_snd_device),
1548 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 /*
1551 * Limitation: While in call, to do a device switch we need to disable
1552 * and enable both RX and TX devices though one of them is same as current
1553 * device.
1554 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001555 if ((usecase->type == VOICE_CALL) &&
1556 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1557 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001558 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001559 }
1560
1561 if (((usecase->type == VOICE_CALL) ||
1562 (usecase->type == VOIP_CALL)) &&
1563 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1564 /* Disable sidetone only if voice/voip call already exists */
1565 if (voice_is_call_state_active(adev) ||
1566 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001567 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001568
1569 /* Disable aanc only if voice call exists */
1570 if (voice_is_call_state_active(adev))
1571 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001572 }
1573
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574 /* Disable current sound devices */
1575 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001576 disable_audio_route(adev, usecase);
1577 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 }
1579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001581 disable_audio_route(adev, usecase);
1582 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 }
1584
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001585 /* Applicable only on the targets that has external modem.
1586 * New device information should be sent to modem before enabling
1587 * the devices to reduce in-call device switch time.
1588 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001589 if ((usecase->type == VOICE_CALL) &&
1590 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1591 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001592 status = platform_switch_voice_call_enable_device_config(adev->platform,
1593 out_snd_device,
1594 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001595 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001596
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001597 /* Enable new sound devices */
1598 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001599 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301600 if (platform_check_codec_asrc_support(adev->platform))
1601 check_and_set_asrc_mode(adev, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001602 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 }
1604
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001605 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301606 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001607 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001608 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001609
Avinash Vaish71a8b972014-07-24 15:36:33 +05301610 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001611 status = platform_switch_voice_call_device_post(adev->platform,
1612 out_snd_device,
1613 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301614 enable_audio_route_for_voice_usecases(adev, usecase);
1615 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001616
sangwoo170731f2013-06-08 15:36:36 +09001617 usecase->in_snd_device = in_snd_device;
1618 usecase->out_snd_device = out_snd_device;
1619
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301620 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1621 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301622 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001623 if ((24 == usecase->stream.out->bit_width) &&
1624 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1625 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1626 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1627 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1628 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1629 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1630 /*
1631 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1632 * configured device sample rate, if not update the COPP rate to be equal to the
1633 * device sample rate, else open COPP at stream sample rate
1634 */
1635 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1636 usecase->stream.out->sample_rate,
1637 &usecase->stream.out->app_type_cfg.sample_rate);
1638 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1639 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1640 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1641 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1642 }
1643
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001644 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001645 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001646 audio_extn_gef_notify_device_config(
1647 usecase->stream.out->devices,
1648 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001649 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001650 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001651 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301652 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001653 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001654
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001655 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001656 /* Enable aanc only if voice call exists */
1657 if (voice_is_call_state_active(adev))
1658 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1659
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001660 /* Enable sidetone only if other voice/voip call already exists */
1661 if (voice_is_call_state_active(adev) ||
1662 voice_extn_compress_voip_is_started(adev))
1663 voice_set_sidetone(adev, out_snd_device, true);
1664 }
1665
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001666 /* Applicable only on the targets that has external modem.
1667 * Enable device command should be sent to modem only after
1668 * enabling voice call mixer controls
1669 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001670 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001671 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1672 out_snd_device,
1673 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301674 ALOGD("%s: done",__func__);
1675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 return status;
1677}
1678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679static int stop_input_stream(struct stream_in *in)
1680{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301681 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682 struct audio_usecase *uc_info;
1683 struct audio_device *adev = in->dev;
1684
Eric Laurent994a6932013-07-17 11:51:42 -07001685 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001686 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687 uc_info = get_usecase_from_list(adev, in->usecase);
1688 if (uc_info == NULL) {
1689 ALOGE("%s: Could not find the usecase (%d) in the list",
1690 __func__, in->usecase);
1691 return -EINVAL;
1692 }
1693
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001694 /* Close in-call recording streams */
1695 voice_check_and_stop_incall_rec_usecase(adev, in);
1696
Eric Laurent150dbfe2013-02-27 14:31:02 -08001697 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001698 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001699
1700 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001701 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001703 list_remove(&uc_info->list);
1704 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001706 adev->active_input = get_next_active_input(adev);
1707
Eric Laurent994a6932013-07-17 11:51:42 -07001708 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709 return ret;
1710}
1711
1712int start_input_stream(struct stream_in *in)
1713{
1714 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001715 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 struct audio_usecase *uc_info;
1717 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301718 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719
Mingming Yin2664a5b2015-09-03 10:53:11 -07001720 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1721 if (get_usecase_from_list(adev, usecase) == NULL)
1722 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301723 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1724 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001725
Naresh Tanniru80659832014-06-04 18:17:56 +05301726
1727 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301728 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301729 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301730 goto error_config;
1731 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301732
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001733 /* Check if source matches incall recording usecase criteria */
1734 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1735 if (ret)
1736 goto error_config;
1737 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001738 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1739
1740 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1741 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1742 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001743 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001744 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001745
Eric Laurentb23d5282013-05-14 15:27:20 -07001746 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 if (in->pcm_device_id < 0) {
1748 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1749 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001750 ret = -EINVAL;
1751 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753
1754 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001756
1757 if (!uc_info) {
1758 ret = -ENOMEM;
1759 goto error_config;
1760 }
1761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 uc_info->id = in->usecase;
1763 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001764 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001765 uc_info->devices = in->device;
1766 uc_info->in_snd_device = SND_DEVICE_NONE;
1767 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001769 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301770 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1771 adev->perf_lock_opts,
1772 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301775 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1776 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001777
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301778 if (audio_extn_cin_attached_usecase(in->usecase)) {
1779 ret = audio_extn_cin_start_input_stream(in);
1780 if (ret)
1781 goto error_open;
1782 else
1783 goto done_open;
1784 }
1785
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001786 unsigned int flags = PCM_IN;
1787 unsigned int pcm_open_retry_count = 0;
1788
1789 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1790 flags |= PCM_MMAP | PCM_NOIRQ;
1791 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001792 } else if (in->realtime) {
1793 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001794 }
1795
1796 while (1) {
1797 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1798 flags, &in->config);
1799 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1800 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1801 if (in->pcm != NULL) {
1802 pcm_close(in->pcm);
1803 in->pcm = NULL;
1804 }
1805 if (pcm_open_retry_count-- == 0) {
1806 ret = -EIO;
1807 goto error_open;
1808 }
1809 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1810 continue;
1811 }
1812 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001814
1815 ALOGV("%s: pcm_prepare", __func__);
1816 ret = pcm_prepare(in->pcm);
1817 if (ret < 0) {
1818 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1819 pcm_close(in->pcm);
1820 in->pcm = NULL;
1821 goto error_open;
1822 }
1823
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001824 register_in_stream(in);
1825 if (in->realtime) {
1826 ret = pcm_start(in->pcm);
1827 if (ret < 0)
1828 goto error_open;
1829 }
1830
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301831done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301832 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001833 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001834
Eric Laurentc8400632013-02-14 19:04:54 -08001835 return ret;
1836
1837error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301838 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001840error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301841 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301842 /*
1843 * sleep 50ms to allow sufficient time for kernel
1844 * drivers to recover incases like SSR.
1845 */
1846 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001847 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001848
1849 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850}
1851
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001852void lock_input_stream(struct stream_in *in)
1853{
1854 pthread_mutex_lock(&in->pre_lock);
1855 pthread_mutex_lock(&in->lock);
1856 pthread_mutex_unlock(&in->pre_lock);
1857}
1858
1859void lock_output_stream(struct stream_out *out)
1860{
1861 pthread_mutex_lock(&out->pre_lock);
1862 pthread_mutex_lock(&out->lock);
1863 pthread_mutex_unlock(&out->pre_lock);
1864}
1865
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001866/* must be called with out->lock locked */
1867static int send_offload_cmd_l(struct stream_out* out, int command)
1868{
1869 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1870
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001871 if (!cmd) {
1872 ALOGE("failed to allocate mem for command 0x%x", command);
1873 return -ENOMEM;
1874 }
1875
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001876 ALOGVV("%s %d", __func__, command);
1877
1878 cmd->cmd = command;
1879 list_add_tail(&out->offload_cmd_list, &cmd->node);
1880 pthread_cond_signal(&out->offload_cond);
1881 return 0;
1882}
1883
1884/* must be called iwth out->lock locked */
1885static void stop_compressed_output_l(struct stream_out *out)
1886{
1887 out->offload_state = OFFLOAD_STATE_IDLE;
1888 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001889 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890 if (out->compr != NULL) {
1891 compress_stop(out->compr);
1892 while (out->offload_thread_blocked) {
1893 pthread_cond_wait(&out->cond, &out->lock);
1894 }
1895 }
1896}
1897
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001898bool is_offload_usecase(audio_usecase_t uc_id)
1899{
1900 unsigned int i;
1901 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1902 if (uc_id == offload_usecases[i])
1903 return true;
1904 }
1905 return false;
1906}
1907
vivek mehta446c3962015-09-14 10:57:35 -07001908static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001909{
vivek mehta446c3962015-09-14 10:57:35 -07001910 audio_usecase_t ret_uc = USECASE_INVALID;
1911 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001912 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001913 if (!adev->multi_offload_enable) {
1914 if (is_direct_pcm)
1915 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1916 else
1917 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001918
vivek mehta446c3962015-09-14 10:57:35 -07001919 pthread_mutex_lock(&adev->lock);
1920 if (get_usecase_from_list(adev, ret_uc) != NULL)
1921 ret_uc = USECASE_INVALID;
1922 pthread_mutex_unlock(&adev->lock);
1923
1924 return ret_uc;
1925 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001926
1927 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001928 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1929 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1930 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1931 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001932 break;
1933 }
1934 }
vivek mehta446c3962015-09-14 10:57:35 -07001935
1936 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1937 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001938}
1939
1940static void free_offload_usecase(struct audio_device *adev,
1941 audio_usecase_t uc_id)
1942{
vivek mehta446c3962015-09-14 10:57:35 -07001943 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001944 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001945
1946 if (!adev->multi_offload_enable)
1947 return;
1948
1949 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1950 if (offload_usecases[offload_uc_index] == uc_id) {
1951 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001952 break;
1953 }
1954 }
1955 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1956}
1957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001958static void *offload_thread_loop(void *context)
1959{
1960 struct stream_out *out = (struct stream_out *) context;
1961 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001962 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1965 set_sched_policy(0, SP_FOREGROUND);
1966 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1967
1968 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001969 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001970 for (;;) {
1971 struct offload_cmd *cmd = NULL;
1972 stream_callback_event_t event;
1973 bool send_callback = false;
1974
1975 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1976 __func__, list_empty(&out->offload_cmd_list),
1977 out->offload_state);
1978 if (list_empty(&out->offload_cmd_list)) {
1979 ALOGV("%s SLEEPING", __func__);
1980 pthread_cond_wait(&out->offload_cond, &out->lock);
1981 ALOGV("%s RUNNING", __func__);
1982 continue;
1983 }
1984
1985 item = list_head(&out->offload_cmd_list);
1986 cmd = node_to_item(item, struct offload_cmd, node);
1987 list_remove(item);
1988
1989 ALOGVV("%s STATE %d CMD %d out->compr %p",
1990 __func__, out->offload_state, cmd->cmd, out->compr);
1991
1992 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1993 free(cmd);
1994 break;
1995 }
1996
1997 if (out->compr == NULL) {
1998 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001999 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002000 pthread_cond_signal(&out->cond);
2001 continue;
2002 }
2003 out->offload_thread_blocked = true;
2004 pthread_mutex_unlock(&out->lock);
2005 send_callback = false;
2006 switch(cmd->cmd) {
2007 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002008 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002010 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 send_callback = true;
2012 event = STREAM_CBK_EVENT_WRITE_READY;
2013 break;
2014 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002015 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302016 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002017 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302018 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002019 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302020 if (ret < 0)
2021 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302022 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302023 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002024 compress_drain(out->compr);
2025 else
2026 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302027 if (ret != -ENETRESET) {
2028 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302029 pthread_mutex_lock(&out->lock);
2030 out->send_new_metadata = 1;
2031 out->send_next_track_params = true;
2032 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302033 event = STREAM_CBK_EVENT_DRAIN_READY;
2034 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2035 } else
2036 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 break;
2038 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002039 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002040 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002041 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 send_callback = true;
2043 event = STREAM_CBK_EVENT_DRAIN_READY;
2044 break;
2045 default:
2046 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2047 break;
2048 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002049 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050 out->offload_thread_blocked = false;
2051 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002052 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002053 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002055 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 free(cmd);
2057 }
2058
2059 pthread_cond_signal(&out->cond);
2060 while (!list_empty(&out->offload_cmd_list)) {
2061 item = list_head(&out->offload_cmd_list);
2062 list_remove(item);
2063 free(node_to_item(item, struct offload_cmd, node));
2064 }
2065 pthread_mutex_unlock(&out->lock);
2066
2067 return NULL;
2068}
2069
2070static int create_offload_callback_thread(struct stream_out *out)
2071{
2072 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2073 list_init(&out->offload_cmd_list);
2074 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2075 offload_thread_loop, out);
2076 return 0;
2077}
2078
2079static int destroy_offload_callback_thread(struct stream_out *out)
2080{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002081 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 stop_compressed_output_l(out);
2083 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2084
2085 pthread_mutex_unlock(&out->lock);
2086 pthread_join(out->offload_thread, (void **) NULL);
2087 pthread_cond_destroy(&out->offload_cond);
2088
2089 return 0;
2090}
2091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092static int stop_output_stream(struct stream_out *out)
2093{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302094 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 struct audio_usecase *uc_info;
2096 struct audio_device *adev = out->dev;
2097
Eric Laurent994a6932013-07-17 11:51:42 -07002098 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 uc_info = get_usecase_from_list(adev, out->usecase);
2101 if (uc_info == NULL) {
2102 ALOGE("%s: Could not find the usecase (%d) in the list",
2103 __func__, out->usecase);
2104 return -EINVAL;
2105 }
2106
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002107 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302108 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002109 if (adev->visualizer_stop_output != NULL)
2110 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002111
2112 audio_extn_dts_remove_state_notifier_node(out->usecase);
2113
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002114 if (adev->offload_effects_stop_output != NULL)
2115 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2116 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002117
Eric Laurent150dbfe2013-02-27 14:31:02 -08002118 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002119 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002120
2121 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002122 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002124 list_remove(&uc_info->list);
2125 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002127 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302128 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 ALOGV("Disable passthrough , reset mixer to pcm");
2130 /* NO_PASSTHROUGH */
2131 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002132 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002133 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2134 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002135
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302136 /* Must be called after removing the usecase from list */
2137 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302138 audio_extn_keep_alive_start();
2139
Eric Laurent994a6932013-07-17 11:51:42 -07002140 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 return ret;
2142}
2143
2144int start_output_stream(struct stream_out *out)
2145{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 struct audio_usecase *uc_info;
2148 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302149 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002151 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2152 ret = -EINVAL;
2153 goto error_config;
2154 }
2155
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302156 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2157 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2158 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302159
Naresh Tanniru80659832014-06-04 18:17:56 +05302160 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302161 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302162 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302163 goto error_config;
2164 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165
Eric Laurentb23d5282013-05-14 15:27:20 -07002166 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 if (out->pcm_device_id < 0) {
2168 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2169 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002170 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002171 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 }
2173
2174 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002175
2176 if (!uc_info) {
2177 ret = -ENOMEM;
2178 goto error_config;
2179 }
2180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 uc_info->id = out->usecase;
2182 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002183 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184 uc_info->devices = out->devices;
2185 uc_info->in_snd_device = SND_DEVICE_NONE;
2186 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002187 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302189 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2190 adev->perf_lock_opts,
2191 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302192
2193 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2194 audio_extn_keep_alive_stop();
2195 if (audio_extn_passthru_is_enabled() &&
2196 audio_extn_passthru_is_passthrough_stream(out)) {
2197 audio_extn_passthru_on_start(out);
2198 audio_extn_passthru_update_stream_configuration(adev, out);
2199 }
2200 }
2201
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002202 select_devices(adev, out->usecase);
2203
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002204 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2205 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002206 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002207 unsigned int flags = PCM_OUT;
2208 unsigned int pcm_open_retry_count = 0;
2209 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2210 flags |= PCM_MMAP | PCM_NOIRQ;
2211 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002212 } else if (out->realtime) {
2213 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002214 } else
2215 flags |= PCM_MONOTONIC;
2216
2217 while (1) {
2218 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2219 flags, &out->config);
2220 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2221 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2222 if (out->pcm != NULL) {
2223 pcm_close(out->pcm);
2224 out->pcm = NULL;
2225 }
2226 if (pcm_open_retry_count-- == 0) {
2227 ret = -EIO;
2228 goto error_open;
2229 }
2230 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2231 continue;
2232 }
2233 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002235
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002236 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2237 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002238
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002239 ALOGV("%s: pcm_prepare", __func__);
2240 if (pcm_is_ready(out->pcm)) {
2241 ret = pcm_prepare(out->pcm);
2242 if (ret < 0) {
2243 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2244 pcm_close(out->pcm);
2245 out->pcm = NULL;
2246 goto error_open;
2247 }
2248 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002250 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2251 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002253 out->compr = compress_open(adev->snd_card,
2254 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255 COMPRESS_IN, &out->compr_config);
2256 if (out->compr && !is_compress_ready(out->compr)) {
2257 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2258 compress_close(out->compr);
2259 out->compr = NULL;
2260 ret = -EIO;
2261 goto error_open;
2262 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302263 /* compress_open sends params of the track, so reset the flag here */
2264 out->is_compr_metadata_avail = false;
2265
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 if (out->offload_callback)
2267 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002268
Fred Oh3f43e742015-03-04 18:42:34 -08002269 /* Since small bufs uses blocking writes, a write will be blocked
2270 for the default max poll time (20s) in the event of an SSR.
2271 Reduce the poll time to observe and deal with SSR faster.
2272 */
Ashish Jain5106d362016-05-11 19:23:33 +05302273 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002274 compress_set_max_poll_wait(out->compr, 1000);
2275 }
2276
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002277 audio_extn_dts_create_state_notifier_node(out->usecase);
2278 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2279 popcount(out->channel_mask),
2280 out->playback_started);
2281
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002282#ifdef DS1_DOLBY_DDP_ENABLED
2283 if (audio_extn_is_dolby_format(out->format))
2284 audio_extn_dolby_send_ddp_endp_params(adev);
2285#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302286 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002287 if (adev->visualizer_start_output != NULL)
2288 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2289 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302290 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002291 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002294
2295 if (ret == 0) {
2296 register_out_stream(out);
2297 if (out->realtime) {
2298 ret = pcm_start(out->pcm);
2299 if (ret < 0)
2300 goto error_open;
2301 }
2302 }
2303
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302304 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002305 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002306
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002307 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002308error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302309 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002311error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302312 /*
2313 * sleep 50ms to allow sufficient time for kernel
2314 * drivers to recover incases like SSR.
2315 */
2316 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002317 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318}
2319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320static int check_input_parameters(uint32_t sample_rate,
2321 audio_format_t format,
2322 int channel_count)
2323{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002324 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302326 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2327 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2328 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002329 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302330 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002331
2332 switch (channel_count) {
2333 case 1:
2334 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302335 case 3:
2336 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002337 case 6:
2338 break;
2339 default:
2340 ret = -EINVAL;
2341 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342
2343 switch (sample_rate) {
2344 case 8000:
2345 case 11025:
2346 case 12000:
2347 case 16000:
2348 case 22050:
2349 case 24000:
2350 case 32000:
2351 case 44100:
2352 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302353 case 96000:
2354 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 break;
2356 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002357 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 }
2359
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002360 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361}
2362
2363static size_t get_input_buffer_size(uint32_t sample_rate,
2364 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002365 int channel_count,
2366 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367{
2368 size_t size = 0;
2369
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002370 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2371 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002373 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002374 if (is_low_latency)
2375 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302376
2377 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002379 /* make sure the size is multiple of 32 bytes
2380 * At 48 kHz mono 16-bit PCM:
2381 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2382 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2383 */
2384 size += 0x1f;
2385 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002386
2387 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388}
2389
Ashish Jain058165c2016-09-28 23:18:48 +05302390static size_t get_output_period_size(uint32_t sample_rate,
2391 audio_format_t format,
2392 int channel_count,
2393 int duration /*in millisecs*/)
2394{
2395 size_t size = 0;
2396 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2397
2398 if ((duration == 0) || (sample_rate == 0) ||
2399 (bytes_per_sample == 0) || (channel_count == 0)) {
2400 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2401 bytes_per_sample, channel_count);
2402 return -EINVAL;
2403 }
2404
2405 size = (sample_rate *
2406 duration *
2407 bytes_per_sample *
2408 channel_count) / 1000;
2409 /*
2410 * To have same PCM samples for all channels, the buffer size requires to
2411 * be multiple of (number of channels * bytes per sample)
2412 * For writes to succeed, the buffer must be written at address which is multiple of 32
2413 */
2414 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2415
2416 return (size/(channel_count * bytes_per_sample));
2417}
2418
Ashish Jain5106d362016-05-11 19:23:33 +05302419static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2420{
2421 uint64_t actual_frames_rendered = 0;
2422 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2423
2424 /* This adjustment accounts for buffering after app processor.
2425 * It is based on estimated DSP latency per use case, rather than exact.
2426 */
2427 int64_t platform_latency = platform_render_latency(out->usecase) *
2428 out->sample_rate / 1000000LL;
2429
2430 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2431 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2432 * hence only estimate.
2433 */
2434 int64_t signed_frames = out->written - kernel_buffer_size;
2435
2436 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2437
2438 if (signed_frames > 0)
2439 actual_frames_rendered = signed_frames;
2440
2441 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2442 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2443 (long long int)out->written, (int)kernel_buffer_size,
2444 audio_bytes_per_sample(out->compr_config.codec->format),
2445 popcount(out->channel_mask));
2446
2447 return actual_frames_rendered;
2448}
2449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2451{
2452 struct stream_out *out = (struct stream_out *)stream;
2453
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455}
2456
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002457static int out_set_sample_rate(struct audio_stream *stream __unused,
2458 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459{
2460 return -ENOSYS;
2461}
2462
2463static size_t out_get_buffer_size(const struct audio_stream *stream)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002467 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002469 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2470 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302471 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302472 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002474 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002475 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476}
2477
2478static uint32_t out_get_channels(const struct audio_stream *stream)
2479{
2480 struct stream_out *out = (struct stream_out *)stream;
2481
2482 return out->channel_mask;
2483}
2484
2485static audio_format_t out_get_format(const struct audio_stream *stream)
2486{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 struct stream_out *out = (struct stream_out *)stream;
2488
2489 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490}
2491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002492static int out_set_format(struct audio_stream *stream __unused,
2493 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494{
2495 return -ENOSYS;
2496}
2497
2498static int out_standby(struct audio_stream *stream)
2499{
2500 struct stream_out *out = (struct stream_out *)stream;
2501 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302503 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2504 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002506 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002508 if (adev->adm_deregister_stream)
2509 adev->adm_deregister_stream(adev->adm_data, out->handle);
2510
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002511 if (is_offload_usecase(out->usecase))
2512 stop_compressed_output_l(out);
2513
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002514 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002516 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2517 voice_extn_compress_voip_close_output_stream(stream);
2518 pthread_mutex_unlock(&adev->lock);
2519 pthread_mutex_unlock(&out->lock);
2520 ALOGD("VOIP output entered standby");
2521 return 0;
2522 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523 if (out->pcm) {
2524 pcm_close(out->pcm);
2525 out->pcm = NULL;
2526 }
2527 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002528 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302529 out->send_next_track_params = false;
2530 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002531 out->gapless_mdata.encoder_delay = 0;
2532 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 if (out->compr != NULL) {
2534 compress_close(out->compr);
2535 out->compr = NULL;
2536 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002539 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 }
2541 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302542 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 return 0;
2544}
2545
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002546static int out_dump(const struct audio_stream *stream __unused,
2547 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548{
2549 return 0;
2550}
2551
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002552static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2553{
2554 int ret = 0;
2555 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002556
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002557 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002558 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002559 return -EINVAL;
2560 }
2561
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302562 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002563
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002564 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2565 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302566 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002567 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002568 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2569 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302570 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002571 }
2572
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002573 ALOGV("%s new encoder delay %u and padding %u", __func__,
2574 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2575
2576 return 0;
2577}
2578
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002579static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2580{
2581 return out == adev->primary_output || out == adev->voice_tx_output;
2582}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2585{
2586 struct stream_out *out = (struct stream_out *)stream;
2587 struct audio_device *adev = out->dev;
2588 struct str_parms *parms;
2589 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002590 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591
sangwoobc677242013-08-08 16:53:43 +09002592 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002593 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302595 if (!parms)
2596 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002597 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2598 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002600 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002601 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002603 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002604 * When HDMI cable is unplugged the music playback is paused and
2605 * the policy manager sends routing=0. But the audioflinger continues
2606 * to write data until standby time (3sec). As the HDMI core is
2607 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002608 * Avoid this by routing audio to speaker until standby.
2609 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002610 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2611 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302612 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002613 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2614 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002615 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302616 /*
2617 * When A2DP is disconnected the
2618 * music playback is paused and the policy manager sends routing=0
2619 * But the audioflingercontinues to write data until standby time
2620 * (3sec). As BT is turned off, the write gets blocked.
2621 * Avoid this by routing audio to speaker until standby.
2622 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002623 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302624 (val == AUDIO_DEVICE_NONE)) {
2625 val = AUDIO_DEVICE_OUT_SPEAKER;
2626 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302627 /* To avoid a2dp to sco overlapping force route BT usecases
2628 * to speaker based on Phone state
2629 */
Ashish Jainc597d102016-12-12 10:31:34 +05302630 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2631 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2632 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2633 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302634 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2635 (adev->mode == AUDIO_MODE_IN_CALL))) {
2636 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2637 val = AUDIO_DEVICE_OUT_SPEAKER;
2638 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002639 /*
2640 * select_devices() call below switches all the usecases on the same
2641 * backend to the new device. Refer to check_usecases_codec_backend() in
2642 * the select_devices(). But how do we undo this?
2643 *
2644 * For example, music playback is active on headset (deep-buffer usecase)
2645 * and if we go to ringtones and select a ringtone, low-latency usecase
2646 * will be started on headset+speaker. As we can't enable headset+speaker
2647 * and headset devices at the same time, select_devices() switches the music
2648 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2649 * So when the ringtone playback is completed, how do we undo the same?
2650 *
2651 * We are relying on the out_set_parameters() call on deep-buffer output,
2652 * once the ringtone playback is ended.
2653 * NOTE: We should not check if the current devices are same as new devices.
2654 * Because select_devices() must be called to switch back the music
2655 * playback to headset.
2656 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002657 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002658 audio_devices_t new_dev = val;
2659 bool same_dev = out->devices == new_dev;
2660 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002661
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002662 if (output_drives_call(adev, out)) {
2663 if(!voice_is_in_call(adev)) {
2664 if (adev->mode == AUDIO_MODE_IN_CALL) {
2665 adev->current_call_output = out;
2666 ret = voice_start_call(adev);
2667 }
2668 } else {
2669 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002670 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002671 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002672 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002673
2674 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002675 if (!same_dev) {
2676 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302677 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2678 adev->perf_lock_opts,
2679 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002680 if (adev->adm_on_routing_change)
2681 adev->adm_on_routing_change(adev->adm_data,
2682 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002683 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002684 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302685 if (!same_dev)
2686 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002687 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002688 }
2689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002691 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002693
2694 if (out == adev->primary_output) {
2695 pthread_mutex_lock(&adev->lock);
2696 audio_extn_set_parameters(adev, parms);
2697 pthread_mutex_unlock(&adev->lock);
2698 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002699 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002700 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002701 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002702
2703 audio_extn_dts_create_state_notifier_node(out->usecase);
2704 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2705 popcount(out->channel_mask),
2706 out->playback_started);
2707
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002708 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002709 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002710
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302711 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2712 if (err >= 0) {
2713 strlcpy(out->profile, value, sizeof(out->profile));
2714 ALOGV("updating stream profile with value '%s'", out->profile);
2715 lock_output_stream(out);
2716 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2717 &adev->streams_output_cfg_list,
2718 out->devices, out->flags, out->format,
2719 out->sample_rate, out->bit_width,
2720 out->channel_mask, out->profile,
2721 &out->app_type_cfg);
2722 pthread_mutex_unlock(&out->lock);
2723 }
2724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302726error:
Eric Laurent994a6932013-07-17 11:51:42 -07002727 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 return ret;
2729}
2730
2731static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2732{
2733 struct stream_out *out = (struct stream_out *)stream;
2734 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002735 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 char value[256];
2737 struct str_parms *reply = str_parms_create();
2738 size_t i, j;
2739 int ret;
2740 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002741
2742 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002743 if (reply) {
2744 str_parms_destroy(reply);
2745 }
2746 if (query) {
2747 str_parms_destroy(query);
2748 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002749 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2750 return NULL;
2751 }
2752
Eric Laurent994a6932013-07-17 11:51:42 -07002753 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2755 if (ret >= 0) {
2756 value[0] = '\0';
2757 i = 0;
2758 while (out->supported_channel_masks[i] != 0) {
2759 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2760 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2761 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002762 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002764 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 first = false;
2766 break;
2767 }
2768 }
2769 i++;
2770 }
2771 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2772 str = str_parms_to_str(reply);
2773 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002774 voice_extn_out_get_parameters(out, query, reply);
2775 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002776 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002777 free(str);
2778 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002781
Alexy Joseph62142aa2015-11-16 15:10:34 -08002782
2783 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2784 if (ret >= 0) {
2785 value[0] = '\0';
2786 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2787 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302788 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002789 } else {
2790 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302791 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002792 }
2793 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002794 if (str)
2795 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002796 str = str_parms_to_str(reply);
2797 }
2798
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002799 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2800 if (ret >= 0) {
2801 value[0] = '\0';
2802 i = 0;
2803 first = true;
2804 while (out->supported_formats[i] != 0) {
2805 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2806 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2807 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002808 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002809 }
2810 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2811 first = false;
2812 break;
2813 }
2814 }
2815 i++;
2816 }
2817 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002818 if (str)
2819 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002820 str = str_parms_to_str(reply);
2821 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002822
2823 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2824 if (ret >= 0) {
2825 value[0] = '\0';
2826 i = 0;
2827 first = true;
2828 while (out->supported_sample_rates[i] != 0) {
2829 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2830 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2831 if (!first) {
2832 strlcat(value, "|", sizeof(value));
2833 }
2834 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2835 first = false;
2836 break;
2837 }
2838 }
2839 i++;
2840 }
2841 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2842 if (str)
2843 free(str);
2844 str = str_parms_to_str(reply);
2845 }
2846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 str_parms_destroy(query);
2848 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002849 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 return str;
2851}
2852
2853static uint32_t out_get_latency(const struct audio_stream_out *stream)
2854{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002855 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002857 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858
Alexy Josephaa54c872014-12-03 02:46:47 -08002859 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002860 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002861 } else if (out->realtime) {
2862 // since the buffer won't be filled up faster than realtime,
2863 // return a smaller number
2864 if (out->config.rate)
2865 period_ms = (out->af_period_multiplier * out->config.period_size *
2866 1000) / (out->config.rate);
2867 else
2868 period_ms = 0;
2869 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002870 } else {
2871 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002873 }
2874
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302875 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002876 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877}
2878
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302879static float AmpToDb(float amplification)
2880{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302881 float db = DSD_VOLUME_MIN_DB;
2882 if (amplification > 0) {
2883 db = 20 * log10(amplification);
2884 if(db < DSD_VOLUME_MIN_DB)
2885 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302886 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302887 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302888}
2889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890static int out_set_volume(struct audio_stream_out *stream, float left,
2891 float right)
2892{
Eric Laurenta9024de2013-04-04 09:19:12 -07002893 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 int volume[2];
2895
Eric Laurenta9024de2013-04-04 09:19:12 -07002896 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2897 /* only take left channel into account: the API is for stereo anyway */
2898 out->muted = (left == 0.0f);
2899 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002900 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302901 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902 /*
2903 * Set mute or umute on HDMI passthrough stream.
2904 * Only take left channel into account.
2905 * Mute is 0 and unmute 1
2906 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302907 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302908 } else if (out->format == AUDIO_FORMAT_DSD){
2909 char mixer_ctl_name[128] = "DSD Volume";
2910 struct audio_device *adev = out->dev;
2911 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2912
2913 if (!ctl) {
2914 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2915 __func__, mixer_ctl_name);
2916 return -EINVAL;
2917 }
2918 volume[0] = (int)(AmpToDb(left));
2919 volume[1] = (int)(AmpToDb(right));
2920 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2921 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002922 } else {
2923 char mixer_ctl_name[128];
2924 struct audio_device *adev = out->dev;
2925 struct mixer_ctl *ctl;
2926 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002927 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002929 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2930 "Compress Playback %d Volume", pcm_device_id);
2931 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2932 if (!ctl) {
2933 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2934 __func__, mixer_ctl_name);
2935 return -EINVAL;
2936 }
2937 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2938 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2939 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2940 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002942 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 return -ENOSYS;
2945}
2946
2947static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2948 size_t bytes)
2949{
2950 struct stream_out *out = (struct stream_out *)stream;
2951 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302952 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002953 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002955 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302956
Naresh Tanniru80659832014-06-04 18:17:56 +05302957 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002958
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302959 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302960 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302961 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2962 pthread_mutex_unlock(&out->lock);
2963 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302964 } else {
2965 /* increase written size during SSR to avoid mismatch
2966 * with the written frames count in AF
2967 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002968 // bytes per frame
2969 size_t bpf = audio_bytes_per_sample(out->format) *
2970 audio_channel_count_from_out_mask(out->channel_mask);
2971 if (bpf != 0)
2972 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302973 ALOGD(" %s: sound card is not active/SSR state", __func__);
2974 ret= -EIO;
2975 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302976 }
2977 }
2978
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302979 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302980 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2981 if (audio_bytes_per_sample(out->format) != 0)
2982 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2983 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302984 goto exit;
2985 }
2986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002988 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002989 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002990 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2991 ret = voice_extn_compress_voip_start_output_stream(out);
2992 else
2993 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002994 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002995 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002997 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 goto exit;
2999 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003000
3001 if (last_known_cal_step != -1) {
3002 ALOGD("%s: retry previous failed cal level set", __func__);
3003 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006
Ashish Jain81eb2a82015-05-13 10:52:34 +05303007 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003008 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303009 adev->is_channel_status_set = true;
3010 }
3011
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003012 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003013 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003014 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003015 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003016 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3017 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303018 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3019 ALOGD("copl(%p):send next track params in gapless", out);
3020 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3021 out->send_next_track_params = false;
3022 out->is_compr_metadata_avail = false;
3023 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003024 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303025 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303026 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003027
Ashish Jain83a6cc22016-06-28 14:34:17 +05303028 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303029 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303030 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303031 pthread_mutex_unlock(&out->lock);
3032 return -EINVAL;
3033 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303034 audio_format_t dst_format = out->hal_op_format;
3035 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303036
3037 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3038 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3039
Ashish Jain83a6cc22016-06-28 14:34:17 +05303040 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303041 dst_format,
3042 buffer,
3043 src_format,
3044 frames);
3045
Ashish Jain83a6cc22016-06-28 14:34:17 +05303046 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303047 bytes_to_write);
3048
3049 /*Convert written bytes in audio flinger format*/
3050 if (ret > 0)
3051 ret = ((ret * format_to_bitwidth_table[out->format]) /
3052 format_to_bitwidth_table[dst_format]);
3053 }
3054 } else
3055 ret = compress_write(out->compr, buffer, bytes);
3056
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303057 if (ret < 0)
3058 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303059 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303060 /*msg to cb thread only if non blocking write is enabled*/
3061 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303062 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303064 } else if (-ENETRESET == ret) {
3065 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3066 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3067 pthread_mutex_unlock(&out->lock);
3068 out_standby(&out->stream.common);
3069 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 }
Ashish Jain5106d362016-05-11 19:23:33 +05303071 if ( ret == (ssize_t)bytes && !out->non_blocking)
3072 out->written += bytes;
3073
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303074 /* Call compr start only when non-zero bytes of data is there to be rendered */
3075 if (!out->playback_started && ret > 0) {
3076 int status = compress_start(out->compr);
3077 if (status < 0) {
3078 ret = status;
3079 ALOGE("%s: compr start failed with err %d", __func__, errno);
3080 goto exit;
3081 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003082 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083 out->playback_started = 1;
3084 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003085
3086 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3087 popcount(out->channel_mask),
3088 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 }
3090 pthread_mutex_unlock(&out->lock);
3091 return ret;
3092 } else {
3093 if (out->pcm) {
3094 if (out->muted)
3095 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003096
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303097 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003098
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003099 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003100
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003101 if (out->config.rate)
3102 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3103 out->config.rate;
3104
3105 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3106
3107 request_out_focus(out, ns);
3108
3109 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003110 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003111 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303112 out->convert_buffer != NULL) {
3113
3114 memcpy_by_audio_format(out->convert_buffer,
3115 out->hal_op_format,
3116 buffer,
3117 out->hal_ip_format,
3118 out->config.period_size * out->config.channels);
3119
3120 ret = pcm_write(out->pcm, out->convert_buffer,
3121 (out->config.period_size *
3122 out->config.channels *
3123 format_to_bitwidth_table[out->hal_op_format]));
3124 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003125 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303126 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003127
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003128 release_out_focus(out);
3129
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303130 if (ret < 0)
3131 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303132 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3133 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3134 else
3135 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 }
3138
3139exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303140 /* ToDo: There may be a corner case when SSR happens back to back during
3141 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303142 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303143 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 }
3145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 pthread_mutex_unlock(&out->lock);
3147
3148 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003149 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003150 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303151 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303152 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303153 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303154 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303155 out->standby = true;
3156 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303158 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3159 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3160 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 }
3162 return bytes;
3163}
3164
3165static int out_get_render_position(const struct audio_stream_out *stream,
3166 uint32_t *dsp_frames)
3167{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003168 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303169 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003170
3171 if (dsp_frames == NULL)
3172 return -EINVAL;
3173
3174 *dsp_frames = 0;
3175 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003176 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303177
3178 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3179 * this operation and adev_close_output_stream(where out gets reset).
3180 */
3181 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3182 *dsp_frames = get_actual_pcm_frames_rendered(out);
3183 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3184 return 0;
3185 }
3186
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003187 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303188 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303189 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303191 if (ret < 0)
3192 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303194 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003195 }
3196 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303197 if (-ENETRESET == ret) {
3198 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3199 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3200 return -EINVAL;
3201 } else if(ret < 0) {
3202 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3203 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303204 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3205 /*
3206 * Handle corner case where compress session is closed during SSR
3207 * and timestamp is queried
3208 */
3209 ALOGE(" ERROR: sound card not active, return error");
3210 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303211 } else {
3212 return 0;
3213 }
Zhou Song32a556e2015-05-05 10:46:56 +08003214 } else if (audio_is_linear_pcm(out->format)) {
3215 *dsp_frames = out->written;
3216 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 } else
3218 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219}
3220
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003221static int out_add_audio_effect(const struct audio_stream *stream __unused,
3222 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223{
3224 return 0;
3225}
3226
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003227static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3228 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229{
3230 return 0;
3231}
3232
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003233static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3234 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235{
3236 return -EINVAL;
3237}
3238
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003239static int out_get_presentation_position(const struct audio_stream_out *stream,
3240 uint64_t *frames, struct timespec *timestamp)
3241{
3242 struct stream_out *out = (struct stream_out *)stream;
3243 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003244 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003245
Ashish Jain5106d362016-05-11 19:23:33 +05303246 /* below piece of code is not guarded against any lock because audioFliner serializes
3247 * this operation and adev_close_output_stream( where out gets reset).
3248 */
3249 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3250 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3251 *frames = get_actual_pcm_frames_rendered(out);
3252 /* this is the best we can do */
3253 clock_gettime(CLOCK_MONOTONIC, timestamp);
3254 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3255 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3256 return 0;
3257 }
3258
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003259 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003260
Ashish Jain5106d362016-05-11 19:23:33 +05303261 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3262 ret = compress_get_tstamp(out->compr, &dsp_frames,
3263 &out->sample_rate);
3264 ALOGVV("%s rendered frames %ld sample_rate %d",
3265 __func__, dsp_frames, out->sample_rate);
3266 *frames = dsp_frames;
3267 if (ret < 0)
3268 ret = -errno;
3269 if (-ENETRESET == ret) {
3270 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3271 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3272 ret = -EINVAL;
3273 } else
3274 ret = 0;
3275 /* this is the best we can do */
3276 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003277 } else {
3278 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003279 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003280 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3281 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003282 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003283 // This adjustment accounts for buffering after app processor.
3284 // It is based on estimated DSP latency per use case, rather than exact.
3285 signed_frames -=
3286 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3287
Eric Laurent949a0892013-09-20 09:20:13 -07003288 // It would be unusual for this value to be negative, but check just in case ...
3289 if (signed_frames >= 0) {
3290 *frames = signed_frames;
3291 ret = 0;
3292 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003293 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303294 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3295 *frames = out->written;
3296 clock_gettime(CLOCK_MONOTONIC, timestamp);
3297 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003298 }
3299 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003300 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003301 return ret;
3302}
3303
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003304static int out_set_callback(struct audio_stream_out *stream,
3305 stream_callback_t callback, void *cookie)
3306{
3307 struct stream_out *out = (struct stream_out *)stream;
3308
3309 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003310 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003311 out->offload_callback = callback;
3312 out->offload_cookie = cookie;
3313 pthread_mutex_unlock(&out->lock);
3314 return 0;
3315}
3316
3317static int out_pause(struct audio_stream_out* stream)
3318{
3319 struct stream_out *out = (struct stream_out *)stream;
3320 int status = -ENOSYS;
3321 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003322 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003323 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003324 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003325 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303326 struct audio_device *adev = out->dev;
3327 int snd_scard_state = get_snd_card_state(adev);
3328
3329 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3330 status = compress_pause(out->compr);
3331
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003333
Mingming Yin21854652016-04-13 11:54:02 -07003334 if (audio_extn_passthru_is_active()) {
3335 ALOGV("offload use case, pause passthru");
3336 audio_extn_passthru_on_pause(out);
3337 }
3338
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303339 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003340 audio_extn_dts_notify_playback_state(out->usecase, 0,
3341 out->sample_rate, popcount(out->channel_mask),
3342 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343 }
3344 pthread_mutex_unlock(&out->lock);
3345 }
3346 return status;
3347}
3348
3349static int out_resume(struct audio_stream_out* stream)
3350{
3351 struct stream_out *out = (struct stream_out *)stream;
3352 int status = -ENOSYS;
3353 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003354 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003355 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003357 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303359 struct audio_device *adev = out->dev;
3360 int snd_scard_state = get_snd_card_state(adev);
3361
Mingming Yin21854652016-04-13 11:54:02 -07003362 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3363 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3364 pthread_mutex_lock(&out->dev->lock);
3365 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003366 pthread_mutex_unlock(&out->dev->lock);
3367 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303368 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003369 }
3370 if (!status) {
3371 out->offload_state = OFFLOAD_STATE_PLAYING;
3372 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303373 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003374 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3375 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376 }
3377 pthread_mutex_unlock(&out->lock);
3378 }
3379 return status;
3380}
3381
3382static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3383{
3384 struct stream_out *out = (struct stream_out *)stream;
3385 int status = -ENOSYS;
3386 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003387 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003388 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3390 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3391 else
3392 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3393 pthread_mutex_unlock(&out->lock);
3394 }
3395 return status;
3396}
3397
3398static int out_flush(struct audio_stream_out* stream)
3399{
3400 struct stream_out *out = (struct stream_out *)stream;
3401 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003402 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003403 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003404 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003405 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3406 stop_compressed_output_l(out);
3407 out->written = 0;
3408 } else {
3409 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3410 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003411 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003412 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 return 0;
3414 }
3415 return -ENOSYS;
3416}
3417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418/** audio_stream_in implementation **/
3419static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3420{
3421 struct stream_in *in = (struct stream_in *)stream;
3422
3423 return in->config.rate;
3424}
3425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003426static int in_set_sample_rate(struct audio_stream *stream __unused,
3427 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428{
3429 return -ENOSYS;
3430}
3431
3432static size_t in_get_buffer_size(const struct audio_stream *stream)
3433{
3434 struct stream_in *in = (struct stream_in *)stream;
3435
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003436 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3437 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003438 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3439 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303440 else if(audio_extn_cin_attached_usecase(in->usecase))
3441 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003442
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003443 return in->config.period_size * in->af_period_multiplier *
3444 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445}
3446
3447static uint32_t in_get_channels(const struct audio_stream *stream)
3448{
3449 struct stream_in *in = (struct stream_in *)stream;
3450
3451 return in->channel_mask;
3452}
3453
3454static audio_format_t in_get_format(const struct audio_stream *stream)
3455{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003456 struct stream_in *in = (struct stream_in *)stream;
3457
3458 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459}
3460
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003461static int in_set_format(struct audio_stream *stream __unused,
3462 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463{
3464 return -ENOSYS;
3465}
3466
3467static int in_standby(struct audio_stream *stream)
3468{
3469 struct stream_in *in = (struct stream_in *)stream;
3470 struct audio_device *adev = in->dev;
3471 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303472 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3473 stream, in->usecase, use_case_table[in->usecase]);
3474
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003475 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003476 if (!in->standby && in->is_st_session) {
3477 ALOGD("%s: sound trigger pcm stop lab", __func__);
3478 audio_extn_sound_trigger_stop_lab(in);
3479 in->standby = 1;
3480 }
3481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003483 if (adev->adm_deregister_stream)
3484 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3485
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003486 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003488 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3489 voice_extn_compress_voip_close_input_stream(stream);
3490 ALOGD("VOIP input entered standby");
3491 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303492 if (audio_extn_cin_attached_usecase(in->usecase))
3493 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003494 if (in->pcm) {
3495 pcm_close(in->pcm);
3496 in->pcm = NULL;
3497 }
3498 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003499 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003500 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 }
3502 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003503 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 return status;
3505}
3506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003507static int in_dump(const struct audio_stream *stream __unused,
3508 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509{
3510 return 0;
3511}
3512
3513static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3514{
3515 struct stream_in *in = (struct stream_in *)stream;
3516 struct audio_device *adev = in->dev;
3517 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003519 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303521 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 parms = str_parms_create_str(kvpairs);
3523
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303524 if (!parms)
3525 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003526 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003527 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003528
3529 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3530 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 val = atoi(value);
3532 /* no audio source uses val == 0 */
3533 if ((in->source != val) && (val != 0)) {
3534 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003535 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3536 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3537 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003538 (in->config.rate == 8000 || in->config.rate == 16000 ||
3539 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003540 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003541 err = voice_extn_compress_voip_open_input_stream(in);
3542 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003543 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003544 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003545 }
3546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 }
3548 }
3549
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003550 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3551 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003553 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 in->device = val;
3555 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003556 if (!in->standby && !in->is_st_session) {
3557 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003558 if (adev->adm_on_routing_change)
3559 adev->adm_on_routing_change(adev->adm_data,
3560 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003561 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 }
3564 }
3565
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303566 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3567 if (err >= 0) {
3568 strlcpy(in->profile, value, sizeof(in->profile));
3569 ALOGV("updating stream profile with value '%s'", in->profile);
3570 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3571 &adev->streams_input_cfg_list,
3572 in->device, in->flags, in->format,
3573 in->sample_rate, in->bit_width,
3574 in->profile, &in->app_type_cfg);
3575 }
3576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003578 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
3580 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303581error:
Eric Laurent994a6932013-07-17 11:51:42 -07003582 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583 return ret;
3584}
3585
3586static char* in_get_parameters(const struct audio_stream *stream,
3587 const char *keys)
3588{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003589 struct stream_in *in = (struct stream_in *)stream;
3590 struct str_parms *query = str_parms_create_str(keys);
3591 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003592 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003593
3594 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003595 if (reply) {
3596 str_parms_destroy(reply);
3597 }
3598 if (query) {
3599 str_parms_destroy(query);
3600 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003601 ALOGE("in_get_parameters: failed to create query or reply");
3602 return NULL;
3603 }
3604
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003605 ALOGV("%s: enter: keys - %s", __func__, keys);
3606
3607 voice_extn_in_get_parameters(in, query, reply);
3608
3609 str = str_parms_to_str(reply);
3610 str_parms_destroy(query);
3611 str_parms_destroy(reply);
3612
3613 ALOGV("%s: exit: returns - %s", __func__, str);
3614 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615}
3616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003617static int in_set_gain(struct audio_stream_in *stream __unused,
3618 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619{
3620 return 0;
3621}
3622
3623static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3624 size_t bytes)
3625{
3626 struct stream_in *in = (struct stream_in *)stream;
3627 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303628 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303629 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303630 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003632 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303633
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003634 if (in->is_st_session) {
3635 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3636 /* Read from sound trigger HAL */
3637 audio_extn_sound_trigger_read(in, buffer, bytes);
3638 pthread_mutex_unlock(&in->lock);
3639 return bytes;
3640 }
3641
Ashish Jainbbce4322016-02-16 13:25:27 +05303642 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003643 ALOGD(" %s: sound card is not active/SSR state", __func__);
3644 ret= -EIO;;
3645 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303646 }
3647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003649 pthread_mutex_lock(&adev->lock);
3650 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3651 ret = voice_extn_compress_voip_start_input_stream(in);
3652 else
3653 ret = start_input_stream(in);
3654 pthread_mutex_unlock(&adev->lock);
3655 if (ret != 0) {
3656 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 }
3658 in->standby = 0;
3659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003661 // what's the duration requested by the client?
3662 long ns = 0;
3663
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303664 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003665 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3666 in->config.rate;
3667
3668 request_in_focus(in, ns);
3669 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003670
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303671 if (audio_extn_cin_attached_usecase(in->usecase)) {
3672 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3673 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303674 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003675 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303676 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003677 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003678 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003679 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303680 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003681 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303682 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3683 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3684 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3685 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303686 ret = -EINVAL;
3687 goto exit;
3688 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303689 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303690 ret = -errno;
3691 }
3692 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303693 /* bytes read is always set to bytes for non compress usecases */
3694 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 }
3696
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003697 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 /*
3700 * Instead of writing zeroes here, we could trust the hardware
3701 * to always provide zeroes when muted.
3702 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303703 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3704 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 memset(buffer, 0, bytes);
3706
3707exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303708 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303709 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003710 if (-ENETRESET == ret)
3711 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 pthread_mutex_unlock(&in->lock);
3714
3715 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303716 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303717 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303718 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303719 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303720 in->standby = true;
3721 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303722 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003724 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303725 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303726 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303728 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729}
3730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003731static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732{
3733 return 0;
3734}
3735
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003736static int add_remove_audio_effect(const struct audio_stream *stream,
3737 effect_handle_t effect,
3738 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003740 struct stream_in *in = (struct stream_in *)stream;
3741 int status = 0;
3742 effect_descriptor_t desc;
3743
3744 status = (*effect)->get_descriptor(effect, &desc);
3745 if (status != 0)
3746 return status;
3747
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003748 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003749 pthread_mutex_lock(&in->dev->lock);
3750 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3751 in->enable_aec != enable &&
3752 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3753 in->enable_aec = enable;
3754 if (!in->standby)
3755 select_devices(in->dev, in->usecase);
3756 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003757 if (in->enable_ns != enable &&
3758 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3759 in->enable_ns = enable;
3760 if (!in->standby)
3761 select_devices(in->dev, in->usecase);
3762 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003763 pthread_mutex_unlock(&in->dev->lock);
3764 pthread_mutex_unlock(&in->lock);
3765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 return 0;
3767}
3768
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003769static int in_add_audio_effect(const struct audio_stream *stream,
3770 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771{
Eric Laurent994a6932013-07-17 11:51:42 -07003772 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003773 return add_remove_audio_effect(stream, effect, true);
3774}
3775
3776static int in_remove_audio_effect(const struct audio_stream *stream,
3777 effect_handle_t effect)
3778{
Eric Laurent994a6932013-07-17 11:51:42 -07003779 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003780 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781}
3782
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303783int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 audio_io_handle_t handle,
3785 audio_devices_t devices,
3786 audio_output_flags_t flags,
3787 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003788 struct audio_stream_out **stream_out,
3789 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790{
3791 struct audio_device *adev = (struct audio_device *)dev;
3792 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303793 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003794 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303797
3798 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3799 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003800 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303801 return -EINVAL;
3802 }
3803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3805
Mingming Yin3a941d42016-02-17 18:08:05 -08003806 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3807 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303808 devices, flags, &out->stream);
3809
3810
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003811 if (!out) {
3812 return -ENOMEM;
3813 }
3814
Haynes Mathew George204045b2015-02-25 20:32:03 -08003815 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003816 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003817 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 if (devices == AUDIO_DEVICE_NONE)
3820 devices = AUDIO_DEVICE_OUT_SPEAKER;
3821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 out->flags = flags;
3823 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003824 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003825 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003826 out->sample_rate = config->sample_rate;
3827 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3828 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003829 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003830 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003831 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303832 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833
Mingming Yin3a941d42016-02-17 18:08:05 -08003834 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3835 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3836 pthread_mutex_lock(&adev->lock);
3837 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3838 ret = read_hdmi_sink_caps(out);
3839 pthread_mutex_unlock(&adev->lock);
3840 if (ret != 0) {
3841 if (ret == -ENOSYS) {
3842 /* ignore and go with default */
3843 ret = 0;
3844 } else {
3845 ALOGE("error reading hdmi sink caps");
3846 goto error_open;
3847 }
3848 }
3849 }
3850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003852 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303853 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3854 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003855 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3856 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3857
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003858 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003859 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3860 /*
3861 * Do not handle stereo output in Multi-channel cases
3862 * Stereo case is handled in normal playback path
3863 */
3864 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3865 ret = AUDIO_CHANNEL_OUT_STEREO;
3866 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003867
3868 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3869 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003870 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003871 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003872 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003873
3874 if (config->sample_rate == 0)
3875 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3876 if (config->channel_mask == 0)
3877 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003878 if (config->format == 0)
3879 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003880
3881 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003882 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003883 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3885 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003887 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003889 } 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 -08003890 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003891 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003892 ret = voice_extn_compress_voip_open_output_stream(out);
3893 if (ret != 0) {
3894 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3895 __func__, ret);
3896 goto error_open;
3897 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003898 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3899 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3900
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003901 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3902 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3903 ALOGE("%s: Unsupported Offload information", __func__);
3904 ret = -EINVAL;
3905 goto error_open;
3906 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003907
Mingming Yin3a941d42016-02-17 18:08:05 -08003908 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003909 if(config->offload_info.format == 0)
3910 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003911 if (config->offload_info.sample_rate == 0)
3912 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003913 }
3914
Mingming Yin90310102013-11-13 16:57:00 -08003915 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303916 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003917 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003918 ret = -EINVAL;
3919 goto error_open;
3920 }
3921
3922 out->compr_config.codec = (struct snd_codec *)
3923 calloc(1, sizeof(struct snd_codec));
3924
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003925 if (!out->compr_config.codec) {
3926 ret = -ENOMEM;
3927 goto error_open;
3928 }
3929
vivek mehta0ea887a2015-08-26 14:01:20 -07003930 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303931 out->stream.pause = out_pause;
3932 out->stream.flush = out_flush;
3933 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003934 out->usecase = get_offload_usecase(adev, true);
3935 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003936 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003937 out->stream.set_callback = out_set_callback;
3938 out->stream.pause = out_pause;
3939 out->stream.resume = out_resume;
3940 out->stream.drain = out_drain;
3941 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003942 out->usecase = get_offload_usecase(adev, false);
3943 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003944 }
vivek mehta446c3962015-09-14 10:57:35 -07003945
3946 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003947 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3948 config->format == 0 && config->sample_rate == 0 &&
3949 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003950 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003951 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3952 } else {
3953 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3954 ret = -EEXIST;
3955 goto error_open;
3956 }
vivek mehta446c3962015-09-14 10:57:35 -07003957 }
3958
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959 if (config->offload_info.channel_mask)
3960 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003961 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003962 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003963 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003964 } else {
3965 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3966 ret = -EINVAL;
3967 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003968 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003969
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003970 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003971 out->sample_rate = config->offload_info.sample_rate;
3972
Mingming Yin3ee55c62014-08-04 14:23:35 -07003973 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003974
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303975 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3976 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3977 audio_extn_dolby_send_ddp_endp_params(adev);
3978 audio_extn_dolby_set_dmid(adev);
3979 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003981 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003982 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 out->compr_config.codec->bit_rate =
3984 config->offload_info.bit_rate;
3985 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303986 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003987 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303988 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003989 /*TODO: Do we need to change it for passthrough */
3990 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003991
Manish Dewangana6fc5442015-08-24 20:30:31 +05303992 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3993 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05303994 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05303995 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05303996 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
3997 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303998
3999 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4000 AUDIO_FORMAT_PCM) {
4001
4002 /*Based on platform support, configure appropriate alsa format for corresponding
4003 *hal input format.
4004 */
4005 out->compr_config.codec->format = hal_format_to_alsa(
4006 config->offload_info.format);
4007
Ashish Jain83a6cc22016-06-28 14:34:17 +05304008 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304009 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304010 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304011
4012 /*for direct PCM playback populate bit_width based on selected alsa format as
4013 *hal input format and alsa format might differ based on platform support.
4014 */
4015 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304016 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304017
4018 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4019
4020 /* Check if alsa session is configured with the same format as HAL input format,
4021 * if not then derive correct fragment size needed to accomodate the
4022 * conversion of HAL input format to alsa format.
4023 */
4024 audio_extn_utils_update_direct_pcm_fragment_size(out);
4025
4026 /*if hal input and output fragment size is different this indicates HAL input format is
4027 *not same as the alsa format
4028 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304029 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304030 /*Allocate a buffer to convert input data to the alsa configured format.
4031 *size of convert buffer is equal to the size required to hold one fragment size
4032 *worth of pcm data, this is because flinger does not write more than fragment_size
4033 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304034 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4035 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304036 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4037 ret = -ENOMEM;
4038 goto error_open;
4039 }
4040 }
4041 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4042 out->compr_config.fragment_size =
4043 audio_extn_passthru_get_buffer_size(&config->offload_info);
4044 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4045 } else {
4046 out->compr_config.fragment_size =
4047 platform_get_compress_offload_buffer_size(&config->offload_info);
4048 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4049 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004050
Amit Shekhar6f461b12014-08-01 14:52:58 -07004051 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304052 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004054 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4055 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004056
Alexy Josephaa54c872014-12-03 02:46:47 -08004057
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004058 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304059 out->send_next_track_params = false;
4060 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004061 out->offload_state = OFFLOAD_STATE_IDLE;
4062 out->playback_started = 0;
4063
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004064 audio_extn_dts_create_state_notifier_node(out->usecase);
4065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4067 __func__, config->offload_info.version,
4068 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304069
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304070 /* Check if DSD audio format is supported in codec
4071 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304072 */
4073
4074 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304075 (!platform_check_codec_dsd_support(adev->platform) ||
4076 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304077 ret = -EINVAL;
4078 goto error_open;
4079 }
4080
Ashish Jain5106d362016-05-11 19:23:33 +05304081 /* Disable gapless if any of the following is true
4082 * passthrough playback
4083 * AV playback
4084 * Direct PCM playback
4085 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304086 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304087 (config->format == AUDIO_FORMAT_DSD) ||
4088 config->offload_info.has_video ||
4089 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304090 check_and_set_gapless_mode(adev, false);
4091 } else
4092 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004093
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304094 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004095 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4096 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304097 if (config->format == AUDIO_FORMAT_DSD) {
4098 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4099 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4100 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004101
4102 create_offload_callback_thread(out);
4103
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004104 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304105 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004106 if (ret != 0) {
4107 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4108 __func__, ret);
4109 goto error_open;
4110 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004111 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4112 if (config->sample_rate == 0)
4113 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4114 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4115 config->sample_rate != 8000) {
4116 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4117 ret = -EINVAL;
4118 goto error_open;
4119 }
4120 out->sample_rate = config->sample_rate;
4121 out->config.rate = config->sample_rate;
4122 if (config->format == AUDIO_FORMAT_DEFAULT)
4123 config->format = AUDIO_FORMAT_PCM_16_BIT;
4124 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4125 config->format = AUDIO_FORMAT_PCM_16_BIT;
4126 ret = -EINVAL;
4127 goto error_open;
4128 }
4129 out->format = config->format;
4130 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4131 out->config = pcm_config_afe_proxy_playback;
4132 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004133 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304134 unsigned int channels = 0;
4135 /*Update config params to default if not set by the caller*/
4136 if (config->sample_rate == 0)
4137 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4138 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4139 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4140 if (config->format == AUDIO_FORMAT_DEFAULT)
4141 config->format = AUDIO_FORMAT_PCM_16_BIT;
4142
4143 channels = audio_channel_count_from_out_mask(out->channel_mask);
4144
Ashish Jain83a6cc22016-06-28 14:34:17 +05304145 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4146 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004147 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4148 out->flags);
4149 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304150 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4151 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4152 out->config = pcm_config_low_latency;
4153 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4154 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4155 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304156 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4157 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4158 if (out->config.period_size <= 0) {
4159 ALOGE("Invalid configuration period size is not valid");
4160 ret = -EINVAL;
4161 goto error_open;
4162 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304163 } else {
4164 /* primary path is the default path selected if no other outputs are available/suitable */
4165 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4166 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4167 }
4168 out->hal_ip_format = format = out->format;
4169 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4170 out->hal_op_format = pcm_format_to_hal(out->config.format);
4171 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4172 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004173 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304174 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304175 if (out->hal_ip_format != out->hal_op_format) {
4176 uint32_t buffer_size = out->config.period_size *
4177 format_to_bitwidth_table[out->hal_op_format] *
4178 out->config.channels;
4179 out->convert_buffer = calloc(1, buffer_size);
4180 if (out->convert_buffer == NULL){
4181 ALOGE("Allocation failed for convert buffer for size %d",
4182 out->compr_config.fragment_size);
4183 ret = -ENOMEM;
4184 goto error_open;
4185 }
4186 ALOGD("Convert buffer allocated of size %d", buffer_size);
4187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 }
4189
Ashish Jain83a6cc22016-06-28 14:34:17 +05304190 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4191 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4192
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004193 /* TODO remove this hardcoding and check why width is zero*/
4194 if (out->bit_width == 0)
4195 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304196 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004197 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07004198 devices, flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304199 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304200 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004201 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4202 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4203 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004204 if(adev->primary_output == NULL)
4205 adev->primary_output = out;
4206 else {
4207 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004208 ret = -EEXIST;
4209 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004210 }
4211 }
4212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213 /* Check if this usecase is already existing */
4214 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004215 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4216 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004219 ret = -EEXIST;
4220 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221 }
4222 pthread_mutex_unlock(&adev->lock);
4223
4224 out->stream.common.get_sample_rate = out_get_sample_rate;
4225 out->stream.common.set_sample_rate = out_set_sample_rate;
4226 out->stream.common.get_buffer_size = out_get_buffer_size;
4227 out->stream.common.get_channels = out_get_channels;
4228 out->stream.common.get_format = out_get_format;
4229 out->stream.common.set_format = out_set_format;
4230 out->stream.common.standby = out_standby;
4231 out->stream.common.dump = out_dump;
4232 out->stream.common.set_parameters = out_set_parameters;
4233 out->stream.common.get_parameters = out_get_parameters;
4234 out->stream.common.add_audio_effect = out_add_audio_effect;
4235 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4236 out->stream.get_latency = out_get_latency;
4237 out->stream.set_volume = out_set_volume;
4238 out->stream.write = out_write;
4239 out->stream.get_render_position = out_get_render_position;
4240 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004241 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004243 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004245 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004246 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247
4248 config->format = out->stream.common.get_format(&out->stream.common);
4249 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4250 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4251
4252 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304253 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004254 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004255
4256 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4257 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4258 popcount(out->channel_mask), out->playback_started);
4259
Eric Laurent994a6932013-07-17 11:51:42 -07004260 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004262
4263error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304264 if (out->convert_buffer)
4265 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004266 free(out);
4267 *stream_out = NULL;
4268 ALOGD("%s: exit: ret %d", __func__, ret);
4269 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270}
4271
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304272void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 struct audio_stream_out *stream)
4274{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004275 struct stream_out *out = (struct stream_out *)stream;
4276 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004277 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004278
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304279 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4280
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004281 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304282 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004283 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304284 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004285 if(ret != 0)
4286 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4287 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004288 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004289 out_standby(&stream->common);
4290
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004291 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004292 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004293 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004294 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004295 if (out->compr_config.codec != NULL)
4296 free(out->compr_config.codec);
4297 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004298
Ashish Jain83a6cc22016-06-28 14:34:17 +05304299 if (out->convert_buffer != NULL) {
4300 free(out->convert_buffer);
4301 out->convert_buffer = NULL;
4302 }
4303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004304 if (adev->voice_tx_output == out)
4305 adev->voice_tx_output = NULL;
4306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004307 pthread_cond_destroy(&out->cond);
4308 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004310 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311}
4312
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004313static void close_compress_sessions(struct audio_device *adev)
4314{
Mingming Yin7b762e72015-03-04 13:47:32 -08004315 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304316 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004317 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004318 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304319
4320 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004321 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304322 if (is_offload_usecase(usecase->id)) {
4323 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004324 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4325 out = usecase->stream.out;
4326 pthread_mutex_unlock(&adev->lock);
4327 out_standby(&out->stream.common);
4328 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004329 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004330 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304331 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004332 }
4333 pthread_mutex_unlock(&adev->lock);
4334}
4335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4337{
4338 struct audio_device *adev = (struct audio_device *)dev;
4339 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004341 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004342 int ret;
4343 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004345 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304348 if (!parms)
4349 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004350 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4351 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304352 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304353 if (strstr(snd_card_status, "OFFLINE")) {
4354 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304355 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004356 //close compress sessions on OFFLINE status
4357 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304358 } else if (strstr(snd_card_status, "ONLINE")) {
4359 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304360 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004361 //send dts hpx license if enabled
4362 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304363 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304364 }
4365
4366 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004367 status = voice_set_parameters(adev, parms);
4368 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004369 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004371 status = platform_set_parameters(adev->platform, parms);
4372 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004373 goto done;
4374
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004375 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4376 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004377 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4379 adev->bluetooth_nrec = true;
4380 else
4381 adev->bluetooth_nrec = false;
4382 }
4383
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004384 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4385 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4387 adev->screen_off = false;
4388 else
4389 adev->screen_off = true;
4390 }
4391
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004392 ret = str_parms_get_int(parms, "rotation", &val);
4393 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004394 bool reverse_speakers = false;
4395 switch(val) {
4396 // FIXME: note that the code below assumes that the speakers are in the correct placement
4397 // relative to the user when the device is rotated 90deg from its default rotation. This
4398 // assumption is device-specific, not platform-specific like this code.
4399 case 270:
4400 reverse_speakers = true;
4401 break;
4402 case 0:
4403 case 90:
4404 case 180:
4405 break;
4406 default:
4407 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004408 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004409 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004410 if (status == 0) {
4411 if (adev->speaker_lr_swap != reverse_speakers) {
4412 adev->speaker_lr_swap = reverse_speakers;
4413 // only update the selected device if there is active pcm playback
4414 struct audio_usecase *usecase;
4415 struct listnode *node;
4416 list_for_each(node, &adev->usecase_list) {
4417 usecase = node_to_item(node, struct audio_usecase, list);
4418 if (usecase->type == PCM_PLAYBACK) {
4419 select_devices(adev, usecase->id);
4420 break;
4421 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004422 }
4423 }
4424 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004425 }
4426
Mingming Yin514a8bc2014-07-29 15:22:21 -07004427 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4428 if (ret >= 0) {
4429 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4430 adev->bt_wb_speech_enabled = true;
4431 else
4432 adev->bt_wb_speech_enabled = false;
4433 }
4434
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004435 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4436 if (ret >= 0) {
4437 val = atoi(value);
4438 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004439 ALOGV("cache new ext disp type and edid");
4440 ret = platform_get_ext_disp_type(adev->platform);
4441 if (ret < 0) {
4442 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004443 status = ret;
4444 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004445 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004446 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004447 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004448 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004449 /*
4450 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4451 * Per AudioPolicyManager, USB device is higher priority than WFD.
4452 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4453 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4454 * starting voice call on USB
4455 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004456 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4457 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004458 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4459 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004460 }
vivek mehta344576a2016-04-12 18:56:03 -07004461 ALOGV("detected USB connect .. disable proxy");
4462 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004463 }
4464 }
4465
4466 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4467 if (ret >= 0) {
4468 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004469 /*
4470 * The HDMI / Displayport disconnect handling has been moved to
4471 * audio extension to ensure that its parameters are not
4472 * invalidated prior to updating sysfs of the disconnect event
4473 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4474 */
4475 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004476 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004477 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4478 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304479 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4480 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004481 }
vivek mehta344576a2016-04-12 18:56:03 -07004482 ALOGV("detected USB disconnect .. enable proxy");
4483 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004484 }
4485 }
4486
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304487 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4488 if (ret >= 0) {
4489 struct audio_usecase *usecase;
4490 struct listnode *node;
4491 list_for_each(node, &adev->usecase_list) {
4492 usecase = node_to_item(node, struct audio_usecase, list);
4493 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004494 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304495 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304496 lock_output_stream(usecase->stream.out);
4497 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304498 //force device switch to re configure encoder
4499 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304500 audio_extn_a2dp_set_handoff_mode(false);
4501 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304502 break;
4503 }
4504 }
4505 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304506 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004507done:
4508 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004509 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304510error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004511 ALOGV("%s: exit with code(%d)", __func__, status);
4512 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513}
4514
4515static char* adev_get_parameters(const struct audio_hw_device *dev,
4516 const char *keys)
4517{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004518 struct audio_device *adev = (struct audio_device *)dev;
4519 struct str_parms *reply = str_parms_create();
4520 struct str_parms *query = str_parms_create_str(keys);
4521 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304522 char value[256] = {0};
4523 int ret = 0;
4524
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004525 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004526 if (reply) {
4527 str_parms_destroy(reply);
4528 }
4529 if (query) {
4530 str_parms_destroy(query);
4531 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004532 ALOGE("adev_get_parameters: failed to create query or reply");
4533 return NULL;
4534 }
4535
Naresh Tannirud7205b62014-06-20 02:54:48 +05304536 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4537 sizeof(value));
4538 if (ret >=0) {
4539 int val = 1;
4540 pthread_mutex_lock(&adev->snd_card_status.lock);
4541 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4542 val = 0;
4543 pthread_mutex_unlock(&adev->snd_card_status.lock);
4544 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4545 goto exit;
4546 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004547
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004548 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004549 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004550 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004551 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304552 pthread_mutex_unlock(&adev->lock);
4553
Naresh Tannirud7205b62014-06-20 02:54:48 +05304554exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004555 str = str_parms_to_str(reply);
4556 str_parms_destroy(query);
4557 str_parms_destroy(reply);
4558
4559 ALOGV("%s: exit: returns - %s", __func__, str);
4560 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561}
4562
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004563static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564{
4565 return 0;
4566}
4567
4568static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4569{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004570 int ret;
4571 struct audio_device *adev = (struct audio_device *)dev;
4572 pthread_mutex_lock(&adev->lock);
4573 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004574 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004575 pthread_mutex_unlock(&adev->lock);
4576 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577}
4578
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004579static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4580 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581{
4582 return -ENOSYS;
4583}
4584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004585static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4586 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587{
4588 return -ENOSYS;
4589}
4590
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004591static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4592 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593{
4594 return -ENOSYS;
4595}
4596
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004597static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4598 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599{
4600 return -ENOSYS;
4601}
4602
4603static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4604{
4605 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 pthread_mutex_lock(&adev->lock);
4608 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004609 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004611 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004612 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004613 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004614 adev->current_call_output = NULL;
4615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 }
4617 pthread_mutex_unlock(&adev->lock);
4618 return 0;
4619}
4620
4621static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4622{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004623 int ret;
4624
4625 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004626 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004627 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4628 pthread_mutex_unlock(&adev->lock);
4629
4630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631}
4632
4633static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4634{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004635 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 return 0;
4637}
4638
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004639static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 const struct audio_config *config)
4641{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004642 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004644 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4645 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646}
4647
4648static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004649 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 audio_devices_t devices,
4651 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004652 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304653 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004654 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004655 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656{
4657 struct audio_device *adev = (struct audio_device *)dev;
4658 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004659 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004660 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004661 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304662 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304665 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4666 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304668 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669
4670 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004671
4672 if (!in) {
4673 ALOGE("failed to allocate input stream");
4674 return -ENOMEM;
4675 }
4676
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304677 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304678 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4679 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004680 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004681 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683 in->stream.common.get_sample_rate = in_get_sample_rate;
4684 in->stream.common.set_sample_rate = in_set_sample_rate;
4685 in->stream.common.get_buffer_size = in_get_buffer_size;
4686 in->stream.common.get_channels = in_get_channels;
4687 in->stream.common.get_format = in_get_format;
4688 in->stream.common.set_format = in_set_format;
4689 in->stream.common.standby = in_standby;
4690 in->stream.common.dump = in_dump;
4691 in->stream.common.set_parameters = in_set_parameters;
4692 in->stream.common.get_parameters = in_get_parameters;
4693 in->stream.common.add_audio_effect = in_add_audio_effect;
4694 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4695 in->stream.set_gain = in_set_gain;
4696 in->stream.read = in_read;
4697 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4698
4699 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004700 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 in->standby = 1;
4703 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004704 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004705 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004707 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004708 if (in->realtime) {
4709 in->config = pcm_config_audio_capture_rt;
4710 in->sample_rate = in->config.rate;
4711 in->af_period_multiplier = af_period_multiplier;
4712 } else {
4713 in->config = pcm_config_audio_capture;
4714 in->config.rate = config->sample_rate;
4715 in->sample_rate = config->sample_rate;
4716 in->af_period_multiplier = 1;
4717 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304718 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304720 /* restrict 24 bit capture for unprocessed source only
4721 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4722 */
4723 if (config->format == AUDIO_FORMAT_DEFAULT) {
4724 config->format = AUDIO_FORMAT_PCM_16_BIT;
4725 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4726 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4727 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4728 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4729 bool ret_error = false;
4730 in->bit_width = 24;
4731 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4732 from HAL is 24_packed and 8_24
4733 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4734 24_packed return error indicating supported format is 24_packed
4735 *> In case of any other source requesting 24 bit or float return error
4736 indicating format supported is 16 bit only.
4737
4738 on error flinger will retry with supported format passed
4739 */
4740 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4741 (source != AUDIO_SOURCE_CAMCORDER)) {
4742 config->format = AUDIO_FORMAT_PCM_16_BIT;
4743 if (config->sample_rate > 48000)
4744 config->sample_rate = 48000;
4745 ret_error = true;
4746 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4747 in->config.format = PCM_FORMAT_S24_3LE;
4748 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4749 in->config.format = PCM_FORMAT_S24_LE;
4750 } else {
4751 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4752 ret_error = true;
4753 }
4754
4755 if (ret_error) {
4756 ret = -EINVAL;
4757 goto err_open;
4758 }
4759 }
4760
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304761 in->usecase = USECASE_AUDIO_RECORD;
4762 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4763 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4764 is_low_latency = true;
4765#if LOW_LATENCY_CAPTURE_USE_CASE
4766 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4767#endif
4768 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4769 }
4770
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304771 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304772 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4773 (adev->mode != AUDIO_MODE_IN_CALL)) {
4774 ret = -EINVAL;
4775 goto err_open;
4776 }
4777
4778 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4779 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004780 if (config->sample_rate == 0)
4781 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4782 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4783 config->sample_rate != 8000) {
4784 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4785 ret = -EINVAL;
4786 goto err_open;
4787 }
4788 if (config->format == AUDIO_FORMAT_DEFAULT)
4789 config->format = AUDIO_FORMAT_PCM_16_BIT;
4790 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4791 config->format = AUDIO_FORMAT_PCM_16_BIT;
4792 ret = -EINVAL;
4793 goto err_open;
4794 }
4795
4796 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4797 in->config = pcm_config_afe_proxy_record;
4798 in->config.channels = channel_count;
4799 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304800 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304801 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4802 in, config, &channel_mask_updated)) {
4803 if (channel_mask_updated == true) {
4804 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4805 __func__, config->channel_mask);
4806 ret = -EINVAL;
4807 goto err_open;
4808 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304809 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004810 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004811 audio_extn_compr_cap_format_supported(config->format) &&
4812 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004813 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304814 } else if (audio_extn_cin_applicable_stream(in)) {
4815 ret = audio_extn_cin_configure_input_stream(in);
4816 if (ret)
4817 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004818 } else {
4819 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004820 if (!in->realtime) {
4821 in->format = config->format;
4822 frame_size = audio_stream_in_frame_size(&in->stream);
4823 buffer_size = get_input_buffer_size(config->sample_rate,
4824 config->format,
4825 channel_count,
4826 is_low_latency);
4827 in->config.period_size = buffer_size / frame_size;
4828 }
4829
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004830 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004831 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004832 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004833 (in->config.rate == 8000 || in->config.rate == 16000 ||
4834 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004835 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4836 voice_extn_compress_voip_open_input_stream(in);
4837 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004839
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304840 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4841 &adev->streams_input_cfg_list,
4842 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304843 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304844
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004845 /* This stream could be for sound trigger lab,
4846 get sound trigger pcm if present */
4847 audio_extn_sound_trigger_check_and_get_session(in);
4848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004850 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004851 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852
4853err_open:
4854 free(in);
4855 *stream_in = NULL;
4856 return ret;
4857}
4858
4859static void adev_close_input_stream(struct audio_hw_device *dev,
4860 struct audio_stream_in *stream)
4861{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004862 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004863 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004864 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304865
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304866 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004867
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304868 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004869 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304870
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004871 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304872 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004873 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304874 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004875 if (ret != 0)
4876 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4877 __func__, ret);
4878 } else
4879 in_standby(&stream->common);
4880
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004881 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004882 audio_extn_ssr_deinit();
4883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304885 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004886 audio_extn_compr_cap_format_supported(in->config.format))
4887 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304888
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304889 if (audio_extn_cin_attached_usecase(in->usecase))
4890 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004891
Mingming Yinfd7607b2016-01-22 12:48:44 -08004892 if (in->is_st_session) {
4893 ALOGV("%s: sound trigger pcm stop lab", __func__);
4894 audio_extn_sound_trigger_stop_lab(in);
4895 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004896 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 return;
4898}
4899
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004900static int adev_dump(const audio_hw_device_t *device __unused,
4901 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902{
4903 return 0;
4904}
4905
4906static int adev_close(hw_device_t *device)
4907{
4908 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004909
4910 if (!adev)
4911 return 0;
4912
4913 pthread_mutex_lock(&adev_init_lock);
4914
4915 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004916 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004917 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304918 audio_extn_utils_release_streams_cfg_lists(
4919 &adev->streams_output_cfg_list,
4920 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304921 if (audio_extn_qaf_is_enabled())
4922 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004923 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004924 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004925 free(adev->snd_dev_ref_cnt);
4926 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004927 if (adev->adm_deinit)
4928 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304929 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004930 free(device);
4931 adev = NULL;
4932 }
4933 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935 return 0;
4936}
4937
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004938/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4939 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4940 * just that it _might_ work.
4941 */
4942static int period_size_is_plausible_for_low_latency(int period_size)
4943{
4944 switch (period_size) {
4945 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004946 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004947 case 240:
4948 case 320:
4949 case 480:
4950 return 1;
4951 default:
4952 return 0;
4953 }
4954}
4955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956static int adev_open(const hw_module_t *module, const char *name,
4957 hw_device_t **device)
4958{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304959 int ret;
4960
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004961 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004962 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4963
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004964 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004965 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004966 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004967 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004968 ALOGD("%s: returning existing instance of adev", __func__);
4969 ALOGD("%s: exit", __func__);
4970 pthread_mutex_unlock(&adev_init_lock);
4971 return 0;
4972 }
4973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974 adev = calloc(1, sizeof(struct audio_device));
4975
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004976 if (!adev) {
4977 pthread_mutex_unlock(&adev_init_lock);
4978 return -ENOMEM;
4979 }
4980
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004981 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4984 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4985 adev->device.common.module = (struct hw_module_t *)module;
4986 adev->device.common.close = adev_close;
4987
4988 adev->device.init_check = adev_init_check;
4989 adev->device.set_voice_volume = adev_set_voice_volume;
4990 adev->device.set_master_volume = adev_set_master_volume;
4991 adev->device.get_master_volume = adev_get_master_volume;
4992 adev->device.set_master_mute = adev_set_master_mute;
4993 adev->device.get_master_mute = adev_get_master_mute;
4994 adev->device.set_mode = adev_set_mode;
4995 adev->device.set_mic_mute = adev_set_mic_mute;
4996 adev->device.get_mic_mute = adev_get_mic_mute;
4997 adev->device.set_parameters = adev_set_parameters;
4998 adev->device.get_parameters = adev_get_parameters;
4999 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5000 adev->device.open_output_stream = adev_open_output_stream;
5001 adev->device.close_output_stream = adev_close_output_stream;
5002 adev->device.open_input_stream = adev_open_input_stream;
5003 adev->device.close_input_stream = adev_close_input_stream;
5004 adev->device.dump = adev_dump;
5005
5006 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005008 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005009 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005012 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005013 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005014 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005015 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005016 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005017 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005018 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005019 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305020 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305021 adev->perf_lock_opts[0] = 0x101;
5022 adev->perf_lock_opts[1] = 0x20E;
5023 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305024
5025 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5026 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005028 adev->platform = platform_init(adev);
5029 if (!adev->platform) {
5030 free(adev->snd_dev_ref_cnt);
5031 free(adev);
5032 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5033 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005034 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305035 pthread_mutex_destroy(&adev->lock);
5036 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005037 return -EINVAL;
5038 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005039
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305040 if (audio_extn_qaf_is_enabled()) {
5041 ret = audio_extn_qaf_init(adev);
5042 if (ret < 0) {
5043 free(adev);
5044 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5045 *device = NULL;
5046 pthread_mutex_unlock(&adev_init_lock);
5047 pthread_mutex_destroy(&adev->lock);
5048 return ret;
5049 }
5050
5051 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5052 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5053 }
5054
Naresh Tanniru4c630392014-05-12 01:05:52 +05305055 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5056
Eric Laurentc4aef752013-09-12 17:45:53 -07005057 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5058 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5059 if (adev->visualizer_lib == NULL) {
5060 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5061 } else {
5062 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5063 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005064 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005065 "visualizer_hal_start_output");
5066 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005067 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005068 "visualizer_hal_stop_output");
5069 }
5070 }
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305071 audio_extn_init();
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005072 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005073 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005074 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005075
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005076 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5077 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5078 if (adev->offload_effects_lib == NULL) {
5079 ALOGE("%s: DLOPEN failed for %s", __func__,
5080 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5081 } else {
5082 ALOGV("%s: DLOPEN successful for %s", __func__,
5083 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5084 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305085 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005086 "offload_effects_bundle_hal_start_output");
5087 adev->offload_effects_stop_output =
5088 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5089 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005090 adev->offload_effects_set_hpx_state =
5091 (int (*)(bool))dlsym(adev->offload_effects_lib,
5092 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305093 adev->offload_effects_get_parameters =
5094 (void (*)(struct str_parms *, struct str_parms *))
5095 dlsym(adev->offload_effects_lib,
5096 "offload_effects_bundle_get_parameters");
5097 adev->offload_effects_set_parameters =
5098 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5099 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005100 }
5101 }
5102
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005103 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5104 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5105 if (adev->adm_lib == NULL) {
5106 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5107 } else {
5108 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5109 adev->adm_init = (adm_init_t)
5110 dlsym(adev->adm_lib, "adm_init");
5111 adev->adm_deinit = (adm_deinit_t)
5112 dlsym(adev->adm_lib, "adm_deinit");
5113 adev->adm_register_input_stream = (adm_register_input_stream_t)
5114 dlsym(adev->adm_lib, "adm_register_input_stream");
5115 adev->adm_register_output_stream = (adm_register_output_stream_t)
5116 dlsym(adev->adm_lib, "adm_register_output_stream");
5117 adev->adm_deregister_stream = (adm_deregister_stream_t)
5118 dlsym(adev->adm_lib, "adm_deregister_stream");
5119 adev->adm_request_focus = (adm_request_focus_t)
5120 dlsym(adev->adm_lib, "adm_request_focus");
5121 adev->adm_abandon_focus = (adm_abandon_focus_t)
5122 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005123 adev->adm_set_config = (adm_set_config_t)
5124 dlsym(adev->adm_lib, "adm_set_config");
5125 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5126 dlsym(adev->adm_lib, "adm_request_focus_v2");
5127 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5128 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5129 adev->adm_on_routing_change = (adm_on_routing_change_t)
5130 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005131 }
5132 }
5133
Mingming Yin514a8bc2014-07-29 15:22:21 -07005134 adev->bt_wb_speech_enabled = false;
5135
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005136 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 *device = &adev->device.common;
5138
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305139 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5140 &adev->streams_output_cfg_list,
5141 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005142
Kiran Kandi910e1862013-10-29 13:29:42 -07005143 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005144
5145 char value[PROPERTY_VALUE_MAX];
5146 int trial;
5147 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5148 trial = atoi(value);
5149 if (period_size_is_plausible_for_low_latency(trial)) {
5150 pcm_config_low_latency.period_size = trial;
5151 pcm_config_low_latency.start_threshold = trial / 4;
5152 pcm_config_low_latency.avail_min = trial / 4;
5153 configured_low_latency_capture_period_size = trial;
5154 }
5155 }
5156 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5157 trial = atoi(value);
5158 if (period_size_is_plausible_for_low_latency(trial)) {
5159 configured_low_latency_capture_period_size = trial;
5160 }
5161 }
5162
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005163 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5164 af_period_multiplier = atoi(value);
5165 if (af_period_multiplier < 0)
5166 af_period_multiplier = 2;
5167 else if (af_period_multiplier > 4)
5168 af_period_multiplier = 4;
5169
5170 ALOGV("new period_multiplier = %d", af_period_multiplier);
5171 }
5172
vivek mehta446c3962015-09-14 10:57:35 -07005173 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005174 pthread_mutex_unlock(&adev_init_lock);
5175
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005176 if (adev->adm_init)
5177 adev->adm_data = adev->adm_init();
5178
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305179 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305180 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005181 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005182 return 0;
5183}
5184
5185static struct hw_module_methods_t hal_module_methods = {
5186 .open = adev_open,
5187};
5188
5189struct audio_module HAL_MODULE_INFO_SYM = {
5190 .common = {
5191 .tag = HARDWARE_MODULE_TAG,
5192 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5193 .hal_api_version = HARDWARE_HAL_API_VERSION,
5194 .id = AUDIO_HARDWARE_MODULE_ID,
5195 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005196 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197 .methods = &hal_module_methods,
5198 },
5199};