blob: dc933d37e552da779bdd26615489685cf5d55e06 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
609static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
610{
611 ALOGV("%s snd device %d", __func__, snd_device);
612 int new_backend_idx = platform_get_backend_index(snd_device);
613
614 if (((new_backend_idx == HEADPHONE_BACKEND) ||
615 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
616 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
617 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618 struct listnode *node = NULL;
619 struct audio_usecase *uc = NULL;
620 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530622
623 list_for_each(node, &adev->usecase_list) {
624 uc = node_to_item(node, struct audio_usecase, list);
625 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530626 if (curr_out && PCM_PLAYBACK == uc->type) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530627 usecase_backend_idx = platform_get_backend_index(uc->out_snd_device);
628
629 if((new_backend_idx == HEADPHONE_BACKEND) &&
630 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
631 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530632 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
633 __func__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530634 enable_asrc_mode(adev);
635 break;
636 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
637 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
638 (usecase_backend_idx == HEADPHONE_BACKEND)) {
639 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
640 __func__);
641 disable_audio_route(adev, uc);
642 disable_snd_device(adev, uc->out_snd_device);
643 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
644 if (new_backend_idx == DSD_NATIVE_BACKEND)
645 audio_route_apply_and_update_path(adev->audio_route,
646 "hph-true-highquality-mode");
647 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
648 (curr_out->bit_width >= 24))
649 audio_route_apply_and_update_path(adev->audio_route,
650 "hph-highquality-mode");
651 enable_asrc_mode(adev);
652 enable_snd_device(adev, uc->out_snd_device);
653 enable_audio_route(adev, uc);
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530654 break;
655 }
656 }
657 }
658 }
659}
660
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700661int pcm_ioctl(struct pcm *pcm, int request, ...)
662{
663 va_list ap;
664 void * arg;
665 int pcm_fd = *(int*)pcm;
666
667 va_start(ap, request);
668 arg = va_arg(ap, void *);
669 va_end(ap);
670
671 return ioctl(pcm_fd, request, arg);
672}
673
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700674int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700675 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800676{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700678 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800679
680 if (usecase == NULL)
681 return -EINVAL;
682
683 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
684
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800685 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800687 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800689
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800690#ifdef DS1_DOLBY_DAP_ENABLED
691 audio_extn_dolby_set_dmid(adev);
692 audio_extn_dolby_set_endpoint(adev);
693#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700694 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700695 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530696 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700697 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530698 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800699 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700700 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700701 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700702 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703 ALOGV("%s: exit", __func__);
704 return 0;
705}
706
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700707int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700708 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700711 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530713 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714 return -EINVAL;
715
716 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 if (usecase->type == PCM_CAPTURE)
718 snd_device = usecase->in_snd_device;
719 else
720 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800721 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700722 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700723 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700724 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700725 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530726 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727 ALOGV("%s: exit", __func__);
728 return 0;
729}
730
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700731int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530734 int i, num_devices = 0;
735 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700736 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
737
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800738 if (snd_device < SND_DEVICE_MIN ||
739 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800740 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800741 return -EINVAL;
742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700743
744 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700745
746 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
747 ALOGE("%s: Invalid sound device returned", __func__);
748 return -EINVAL;
749 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700751 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700752 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 return 0;
754 }
755
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530756
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700757 if (audio_extn_spkr_prot_is_enabled())
758 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700759
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800760 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
761 audio_extn_spkr_prot_is_enabled()) {
762 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700763 adev->snd_dev_ref_cnt[snd_device]--;
764 return -EINVAL;
765 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200766 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800767 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800768 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200769 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800770 return -EINVAL;
771 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700772 } else if (platform_split_snd_device(adev->platform,
773 snd_device,
774 &num_devices,
775 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530776 for (i = 0; i < num_devices; i++) {
777 enable_snd_device(adev, new_snd_devices[i]);
778 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800779 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700780 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530781
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530782 if (platform_check_codec_asrc_support(adev->platform))
783 check_and_set_asrc_mode(adev, snd_device);
784
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530785 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
786 (audio_extn_a2dp_start_playback() < 0)) {
787 ALOGE(" fail to configure A2dp control path ");
788 return -EINVAL;
789 }
790
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700791 /* due to the possibility of calibration overwrite between listen
792 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700793 audio_extn_sound_trigger_update_device_status(snd_device,
794 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530795 audio_extn_listen_update_device_status(snd_device,
796 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700797 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700798 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700799 audio_extn_sound_trigger_update_device_status(snd_device,
800 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530801 audio_extn_listen_update_device_status(snd_device,
802 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700803 return -EINVAL;
804 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300805 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700806 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530807
808 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
809 !adev->native_playback_enabled &&
810 audio_is_true_native_stream_active(adev)) {
811 ALOGD("%s: %d: napb: enabling native mode in hardware",
812 __func__, __LINE__);
813 audio_route_apply_and_update_path(adev->audio_route,
814 "true-native-mode");
815 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818 return 0;
819}
820
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700821int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700822 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800823{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530824 int i, num_devices = 0;
825 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700826 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
827
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800828 if (snd_device < SND_DEVICE_MIN ||
829 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800830 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800831 return -EINVAL;
832 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
834 ALOGE("%s: device ref cnt is already 0", __func__);
835 return -EINVAL;
836 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700837
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700839
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700840 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
841 ALOGE("%s: Invalid sound device returned", __func__);
842 return -EINVAL;
843 }
844
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700846 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530847
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800848 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
849 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700850 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700851 } else if (platform_split_snd_device(adev->platform,
852 snd_device,
853 &num_devices,
854 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530855 for (i = 0; i < num_devices; i++) {
856 disable_snd_device(adev, new_snd_devices[i]);
857 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300858 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700859 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300860 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700861
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530862 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
863 audio_extn_a2dp_stop_playback();
864
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700865 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530866 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
868 adev->native_playback_enabled) {
869 ALOGD("%s: %d: napb: disabling native mode in hardware",
870 __func__, __LINE__);
871 audio_route_reset_and_update_path(adev->audio_route,
872 "true-native-mode");
873 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530874 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
875 adev->asrc_mode_enabled) {
876 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530877 disable_asrc_mode(adev);
878 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530879 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530880
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200881 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700882 audio_extn_sound_trigger_update_device_status(snd_device,
883 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530884 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800885 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888 return 0;
889}
890
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700891/*
892 legend:
893 uc - existing usecase
894 new_uc - new usecase
895 d1, d11, d2 - SND_DEVICE enums
896 a1, a2 - corresponding ANDROID device enums
897 B1, B2 - backend strings
898
899case 1
900 uc->dev d1 (a1) B1
901 new_uc->dev d1 (a1), d2 (a2) B1, B2
902
903 resolution: disable and enable uc->dev on d1
904
905case 2
906 uc->dev d1 (a1) B1
907 new_uc->dev d11 (a1) B1
908
909 resolution: need to switch uc since d1 and d11 are related
910 (e.g. speaker and voice-speaker)
911 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
912
913case 3
914 uc->dev d1 (a1) B1
915 new_uc->dev d2 (a2) B2
916
917 resolution: no need to switch uc
918
919case 4
920 uc->dev d1 (a1) B1
921 new_uc->dev d2 (a2) B1
922
923 resolution: disable enable uc-dev on d2 since backends match
924 we cannot enable two streams on two different devices if they
925 share the same backend. e.g. if offload is on speaker device using
926 QUAD_MI2S backend and a low-latency stream is started on voice-handset
927 using the same backend, offload must also be switched to voice-handset.
928
929case 5
930 uc->dev d1 (a1) B1
931 new_uc->dev d1 (a1), d2 (a2) B1
932
933 resolution: disable enable uc-dev on d2 since backends match
934 we cannot enable two streams on two different devices if they
935 share the same backend.
936
937case 6
938 uc->dev d1 (a1) B1
939 new_uc->dev d2 (a1) B2
940
941 resolution: no need to switch
942
943case 7
944 uc->dev d1 (a1), d2 (a2) B1, B2
945 new_uc->dev d1 (a1) B1
946
947 resolution: no need to switch
948
949*/
950static snd_device_t derive_playback_snd_device(void * platform,
951 struct audio_usecase *uc,
952 struct audio_usecase *new_uc,
953 snd_device_t new_snd_device)
954{
955 audio_devices_t a1 = uc->stream.out->devices;
956 audio_devices_t a2 = new_uc->stream.out->devices;
957
958 snd_device_t d1 = uc->out_snd_device;
959 snd_device_t d2 = new_snd_device;
960
961 // Treat as a special case when a1 and a2 are not disjoint
962 if ((a1 != a2) && (a1 & a2)) {
963 snd_device_t d3[2];
964 int num_devices = 0;
965 int ret = platform_split_snd_device(platform,
966 popcount(a1) > 1 ? d1 : d2,
967 &num_devices,
968 d3);
969 if (ret < 0) {
970 if (ret != -ENOSYS) {
971 ALOGW("%s failed to split snd_device %d",
972 __func__,
973 popcount(a1) > 1 ? d1 : d2);
974 }
975 goto end;
976 }
977
978 // NB: case 7 is hypothetical and isn't a practical usecase yet.
979 // But if it does happen, we need to give priority to d2 if
980 // the combo devices active on the existing usecase share a backend.
981 // This is because we cannot have a usecase active on a combo device
982 // and a new usecase requests one device in this combo pair.
983 if (platform_check_backends_match(d3[0], d3[1])) {
984 return d2; // case 5
985 } else {
986 return d1; // case 1
987 }
988 } else {
989 if (platform_check_backends_match(d1, d2)) {
990 return d2; // case 2, 4
991 } else {
992 return d1; // case 6, 3
993 }
994 }
995
996end:
997 return d2; // return whatever was calculated before.
998}
999
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301001 struct audio_usecase *uc_info,
1002 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003{
1004 struct listnode *node;
1005 struct audio_usecase *usecase;
1006 bool switch_device[AUDIO_USECASE_MAX];
1007 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001008 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301009 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010 /*
1011 * This function is to make sure that all the usecases that are active on
1012 * the hardware codec backend are always routed to any one device that is
1013 * handled by the hardware codec.
1014 * For example, if low-latency and deep-buffer usecases are currently active
1015 * on speaker and out_set_parameters(headset) is received on low-latency
1016 * output, then we have to make sure deep-buffer is also switched to headset,
1017 * because of the limitation that both the devices cannot be enabled
1018 * at the same time as they share the same backend.
1019 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001020 /*
1021 * This call is to check if we need to force routing for a particular stream
1022 * If there is a backend configuration change for the device when a
1023 * new stream starts, then ADM needs to be closed and re-opened with the new
1024 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001025 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001026 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001027 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1028 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301029 /* For a2dp device reconfigure all active sessions
1030 * with new AFE encoder format based on a2dp state
1031 */
1032 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1033 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1034 audio_extn_a2dp_is_force_device_switch()) {
1035 force_routing = true;
1036 force_restart_session = true;
1037 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301038 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1039
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001041 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001042 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1044 switch_device[i] = false;
1045
1046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001048
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301049 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1050 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301051 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301052 platform_get_snd_device_name(usecase->out_snd_device),
1053 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001054 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301055 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001056 (derive_playback_snd_device(adev->platform,
1057 usecase, uc_info,
1058 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301059 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1060 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301061 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301062 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1063 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1064 ((force_restart_session) ||
1065 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301066
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301067 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1068 __func__, use_case_table[usecase->id],
1069 platform_get_snd_device_name(usecase->out_snd_device));
1070 disable_audio_route(adev, usecase);
1071 switch_device[usecase->id] = true;
1072 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 }
1074 }
1075
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301076 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1077 num_uc_to_switch);
1078
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001080 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301082 /* Make sure the previous devices to be disabled first and then enable the
1083 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 list_for_each(node, &adev->usecase_list) {
1085 usecase = node_to_item(node, struct audio_usecase, list);
1086 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001087 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 }
1089 }
1090
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001091 list_for_each(node, &adev->usecase_list) {
1092 usecase = node_to_item(node, struct audio_usecase, list);
1093 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001094 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001095 }
1096 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 /* Re-route all the usecases on the shared backend other than the
1099 specified usecase to new snd devices */
1100 list_for_each(node, &adev->usecase_list) {
1101 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301102 /* Update the out_snd_device only before enabling the audio route */
1103 if (switch_device[usecase->id]) {
1104 usecase->out_snd_device = snd_device;
1105 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301106 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301107 use_case_table[usecase->id],
1108 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001109 /* Update voc calibration before enabling VoIP route */
1110 if (usecase->type == VOIP_CALL)
1111 status = platform_switch_voice_call_device_post(adev->platform,
1112 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001113 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301114 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 }
1117 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118 }
1119}
1120
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301121static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001122 struct audio_usecase *uc_info,
1123 snd_device_t snd_device)
1124{
1125 struct listnode *node;
1126 struct audio_usecase *usecase;
1127 bool switch_device[AUDIO_USECASE_MAX];
1128 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301129 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001130 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001131
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301132 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1133 snd_device);
1134 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301135
1136 /*
1137 * Make sure out devices is checked against out codec backend device and
1138 * also in devices against in codec backend. Checking out device against in
1139 * codec backend or vice versa causes issues.
1140 */
1141 if (uc_info->type == PCM_CAPTURE)
1142 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001143 /*
1144 * This function is to make sure that all the active capture usecases
1145 * are always routed to the same input sound device.
1146 * For example, if audio-record and voice-call usecases are currently
1147 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1148 * is received for voice call then we have to make sure that audio-record
1149 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1150 * because of the limitation that two devices cannot be enabled
1151 * at the same time if they share the same backend.
1152 */
1153 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1154 switch_device[i] = false;
1155
1156 list_for_each(node, &adev->usecase_list) {
1157 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301158 /*
1159 * TODO: Enhance below condition to handle BT sco/USB multi recording
1160 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001161 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301163 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301164 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301165 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001166 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001167 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1169 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001170 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001171 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001172 switch_device[usecase->id] = true;
1173 num_uc_to_switch++;
1174 }
1175 }
1176
1177 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001178 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301180 /* Make sure the previous devices to be disabled first and then enable the
1181 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001182 list_for_each(node, &adev->usecase_list) {
1183 usecase = node_to_item(node, struct audio_usecase, list);
1184 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001185 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001186 }
1187 }
1188
1189 list_for_each(node, &adev->usecase_list) {
1190 usecase = node_to_item(node, struct audio_usecase, list);
1191 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001192 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001193 }
1194 }
1195
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001196 /* Re-route all the usecases on the shared backend other than the
1197 specified usecase to new snd devices */
1198 list_for_each(node, &adev->usecase_list) {
1199 usecase = node_to_item(node, struct audio_usecase, list);
1200 /* Update the in_snd_device only before enabling the audio route */
1201 if (switch_device[usecase->id] ) {
1202 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001203 if (usecase->type != VOICE_CALL) {
1204 /* Update voc calibration before enabling VoIP route */
1205 if (usecase->type == VOIP_CALL)
1206 status = platform_switch_voice_call_device_post(adev->platform,
1207 usecase->out_snd_device,
1208 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301209 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001210 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001211 }
1212 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 }
1214}
1215
Mingming Yin3a941d42016-02-17 18:08:05 -08001216static void reset_hdmi_sink_caps(struct stream_out *out) {
1217 int i = 0;
1218
1219 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1220 out->supported_channel_masks[i] = 0;
1221 }
1222 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1223 out->supported_formats[i] = 0;
1224 }
1225 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1226 out->supported_sample_rates[i] = 0;
1227 }
1228}
1229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001231static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Mingming Yin3a941d42016-02-17 18:08:05 -08001233 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001234 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235
Mingming Yin3a941d42016-02-17 18:08:05 -08001236 reset_hdmi_sink_caps(out);
1237
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001238 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001239 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001240 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001241 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001242 }
1243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001246 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001247 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001248 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1249 case 6:
1250 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1251 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1252 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1253 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1254 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1255 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256 break;
1257 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001258 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001259 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001260 break;
1261 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001262
1263 // check channel format caps
1264 i = 0;
1265 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1266 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1267 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1268 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1269 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1270 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1271 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1272 }
1273
1274 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1275 ALOGV(":%s HDMI supports DTS format", __func__);
1276 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1277 }
1278
1279 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1280 ALOGV(":%s HDMI supports DTS HD format", __func__);
1281 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1282 }
1283
1284
1285 // check sample rate caps
1286 i = 0;
1287 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1288 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1289 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1290 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1291 }
1292 }
1293
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001294 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295}
1296
Alexy Josephb1379942016-01-29 15:49:38 -08001297audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001298 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001299{
1300 struct audio_usecase *usecase;
1301 struct listnode *node;
1302
1303 list_for_each(node, &adev->usecase_list) {
1304 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001305 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001306 ALOGV("%s: usecase id %d", __func__, usecase->id);
1307 return usecase->id;
1308 }
1309 }
1310 return USECASE_INVALID;
1311}
1312
Alexy Josephb1379942016-01-29 15:49:38 -08001313struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001314 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315{
1316 struct audio_usecase *usecase;
1317 struct listnode *node;
1318
1319 list_for_each(node, &adev->usecase_list) {
1320 usecase = node_to_item(node, struct audio_usecase, list);
1321 if (usecase->id == uc_id)
1322 return usecase;
1323 }
1324 return NULL;
1325}
1326
Dhananjay Kumard4833242016-10-06 22:09:12 +05301327struct stream_in *get_next_active_input(const struct audio_device *adev)
1328{
1329 struct audio_usecase *usecase;
1330 struct listnode *node;
1331
1332 list_for_each_reverse(node, &adev->usecase_list) {
1333 usecase = node_to_item(node, struct audio_usecase, list);
1334 if (usecase->type == PCM_CAPTURE)
1335 return usecase->stream.in;
1336 }
1337 return NULL;
1338}
1339
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301340/*
1341 * is a true native playback active
1342 */
1343bool audio_is_true_native_stream_active(struct audio_device *adev)
1344{
1345 bool active = false;
1346 int i = 0;
1347 struct listnode *node;
1348
1349 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1350 ALOGV("%s:napb: not in true mode or non hdphones device",
1351 __func__);
1352 active = false;
1353 goto exit;
1354 }
1355
1356 list_for_each(node, &adev->usecase_list) {
1357 struct audio_usecase *uc;
1358 uc = node_to_item(node, struct audio_usecase, list);
1359 struct stream_out *curr_out =
1360 (struct stream_out*) uc->stream.out;
1361
1362 if (curr_out && PCM_PLAYBACK == uc->type) {
1363 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1364 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1365 uc->id, curr_out->sample_rate,
1366 curr_out->bit_width,
1367 platform_get_snd_device_name(uc->out_snd_device));
1368
1369 if (is_offload_usecase(uc->id) &&
1370 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1371 active = true;
1372 ALOGD("%s:napb:native stream detected", __func__);
1373 }
1374 }
1375 }
1376exit:
1377 return active;
1378}
1379
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301380/*
1381 * if native DSD playback active
1382 */
1383bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1384{
1385 bool active = false;
1386 struct listnode *node = NULL;
1387 struct audio_usecase *uc = NULL;
1388 struct stream_out *curr_out = NULL;
1389
1390 list_for_each(node, &adev->usecase_list) {
1391 uc = node_to_item(node, struct audio_usecase, list);
1392 curr_out = (struct stream_out*) uc->stream.out;
1393
1394 if (curr_out && PCM_PLAYBACK == uc->type &&
1395 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1396 active = true;
1397 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301398 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301399 }
1400 }
1401 return active;
1402}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301403
1404static bool force_device_switch(struct audio_usecase *usecase)
1405{
1406 bool ret = false;
1407 bool is_it_true_mode = false;
1408
1409 if (is_offload_usecase(usecase->id) &&
1410 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001411 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1412 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1413 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301414 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1415 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1416 (!is_it_true_mode && adev->native_playback_enabled)){
1417 ret = true;
1418 ALOGD("napb: time to toggle native mode");
1419 }
1420 }
1421
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301422 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301423 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1424 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301425 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001426 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301427 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301428 ALOGD("Force a2dp device switch to update new encoder config");
1429 ret = true;
1430 }
1431
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301432 return ret;
1433}
1434
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001435int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001437 snd_device_t out_snd_device = SND_DEVICE_NONE;
1438 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 struct audio_usecase *usecase = NULL;
1440 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001441 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001442 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001443 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301446 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 usecase = get_usecase_from_list(adev, uc_id);
1449 if (usecase == NULL) {
1450 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1451 return -EINVAL;
1452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001454 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001455 (usecase->type == VOIP_CALL) ||
1456 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301457 if(usecase->stream.out == NULL) {
1458 ALOGE("%s: stream.out is NULL", __func__);
1459 return -EINVAL;
1460 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001461 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001462 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001463 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 usecase->devices = usecase->stream.out->devices;
1465 } else {
1466 /*
1467 * If the voice call is active, use the sound devices of voice call usecase
1468 * so that it would not result any device switch. All the usecases will
1469 * be switched to new device when select_devices() is called for voice call
1470 * usecase. This is to avoid switching devices for voice call when
1471 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001472 * choose voice call device only if the use case device is
1473 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001475 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001476 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001477 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001478 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1479 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301480 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1481 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001482 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 in_snd_device = vc_usecase->in_snd_device;
1484 out_snd_device = vc_usecase->out_snd_device;
1485 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001486 } else if (voice_extn_compress_voip_is_active(adev)) {
1487 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001488 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001489 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1490 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001491 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001492 in_snd_device = voip_usecase->in_snd_device;
1493 out_snd_device = voip_usecase->out_snd_device;
1494 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001495 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001496 hfp_ucid = audio_extn_hfp_get_usecase();
1497 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001498 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001499 in_snd_device = hfp_usecase->in_snd_device;
1500 out_snd_device = hfp_usecase->out_snd_device;
1501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 }
1503 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301504 if (usecase->stream.out == NULL) {
1505 ALOGE("%s: stream.out is NULL", __func__);
1506 return -EINVAL;
1507 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 usecase->devices = usecase->stream.out->devices;
1509 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001510 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001511 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001512 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001513 if (usecase->stream.out == adev->primary_output &&
1514 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001515 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001516 select_devices(adev, adev->active_input->usecase);
1517 }
1518 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301520 if (usecase->stream.in == NULL) {
1521 ALOGE("%s: stream.in is NULL", __func__);
1522 return -EINVAL;
1523 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524 usecase->devices = usecase->stream.in->device;
1525 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001526 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001527 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001528 if (adev->active_input &&
1529 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301530 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1531 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1532 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001533 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001534 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001535 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1536 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001537 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001538 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001539 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540 }
1541 }
1542
1543 if (out_snd_device == usecase->out_snd_device &&
1544 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301545
1546 if (!force_device_switch(usecase))
1547 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 }
1549
sangwoobc677242013-08-08 16:53:43 +09001550 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001551 out_snd_device, platform_get_snd_device_name(out_snd_device),
1552 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 /*
1555 * Limitation: While in call, to do a device switch we need to disable
1556 * and enable both RX and TX devices though one of them is same as current
1557 * device.
1558 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001559 if ((usecase->type == VOICE_CALL) &&
1560 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1561 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001562 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001563 }
1564
1565 if (((usecase->type == VOICE_CALL) ||
1566 (usecase->type == VOIP_CALL)) &&
1567 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1568 /* Disable sidetone only if voice/voip call already exists */
1569 if (voice_is_call_state_active(adev) ||
1570 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001571 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001572
1573 /* Disable aanc only if voice call exists */
1574 if (voice_is_call_state_active(adev))
1575 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001576 }
1577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 /* Disable current sound devices */
1579 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001580 disable_audio_route(adev, usecase);
1581 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
1583
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001585 disable_audio_route(adev, usecase);
1586 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 }
1588
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001589 /* Applicable only on the targets that has external modem.
1590 * New device information should be sent to modem before enabling
1591 * the devices to reduce in-call device switch time.
1592 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001593 if ((usecase->type == VOICE_CALL) &&
1594 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1595 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001596 status = platform_switch_voice_call_enable_device_config(adev->platform,
1597 out_snd_device,
1598 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001599 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001600
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 /* Enable new sound devices */
1602 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001603 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 }
1606
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001607 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301608 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001609 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001611
Avinash Vaish71a8b972014-07-24 15:36:33 +05301612 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001613 status = platform_switch_voice_call_device_post(adev->platform,
1614 out_snd_device,
1615 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301616 enable_audio_route_for_voice_usecases(adev, usecase);
1617 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001618
sangwoo170731f2013-06-08 15:36:36 +09001619 usecase->in_snd_device = in_snd_device;
1620 usecase->out_snd_device = out_snd_device;
1621
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301622 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1623 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301624 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001625 if ((24 == usecase->stream.out->bit_width) &&
1626 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1627 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1628 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1629 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1630 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1631 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1632 /*
1633 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1634 * configured device sample rate, if not update the COPP rate to be equal to the
1635 * device sample rate, else open COPP at stream sample rate
1636 */
1637 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1638 usecase->stream.out->sample_rate,
1639 &usecase->stream.out->app_type_cfg.sample_rate);
1640 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1641 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1642 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1643 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1644 }
1645
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001646 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001647 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001648 audio_extn_gef_notify_device_config(
1649 usecase->stream.out->devices,
1650 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001651 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001652 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001653 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301654 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001655 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001656
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001657 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001658 /* Enable aanc only if voice call exists */
1659 if (voice_is_call_state_active(adev))
1660 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1661
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001662 /* Enable sidetone only if other voice/voip call already exists */
1663 if (voice_is_call_state_active(adev) ||
1664 voice_extn_compress_voip_is_started(adev))
1665 voice_set_sidetone(adev, out_snd_device, true);
1666 }
1667
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001668 /* Applicable only on the targets that has external modem.
1669 * Enable device command should be sent to modem only after
1670 * enabling voice call mixer controls
1671 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001672 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001673 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1674 out_snd_device,
1675 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301676 ALOGD("%s: done",__func__);
1677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 return status;
1679}
1680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681static int stop_input_stream(struct stream_in *in)
1682{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301683 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 struct audio_usecase *uc_info;
1685 struct audio_device *adev = in->dev;
1686
Eric Laurent994a6932013-07-17 11:51:42 -07001687 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001688 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 uc_info = get_usecase_from_list(adev, in->usecase);
1690 if (uc_info == NULL) {
1691 ALOGE("%s: Could not find the usecase (%d) in the list",
1692 __func__, in->usecase);
1693 return -EINVAL;
1694 }
1695
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001696 /* Close in-call recording streams */
1697 voice_check_and_stop_incall_rec_usecase(adev, in);
1698
Eric Laurent150dbfe2013-02-27 14:31:02 -08001699 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001700 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701
1702 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001703 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001705 list_remove(&uc_info->list);
1706 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001708 adev->active_input = get_next_active_input(adev);
1709
Eric Laurent994a6932013-07-17 11:51:42 -07001710 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 return ret;
1712}
1713
1714int start_input_stream(struct stream_in *in)
1715{
1716 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001717 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 struct audio_usecase *uc_info;
1719 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301720 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721
Mingming Yin2664a5b2015-09-03 10:53:11 -07001722 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1723 if (get_usecase_from_list(adev, usecase) == NULL)
1724 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301725 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1726 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001727
Naresh Tanniru80659832014-06-04 18:17:56 +05301728
1729 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301730 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301731 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301732 goto error_config;
1733 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301734
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001735 /* Check if source matches incall recording usecase criteria */
1736 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1737 if (ret)
1738 goto error_config;
1739 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001740 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1741
1742 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1743 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1744 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001745 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001746 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001747
Eric Laurentb23d5282013-05-14 15:27:20 -07001748 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 if (in->pcm_device_id < 0) {
1750 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1751 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001752 ret = -EINVAL;
1753 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755
1756 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001758
1759 if (!uc_info) {
1760 ret = -ENOMEM;
1761 goto error_config;
1762 }
1763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764 uc_info->id = in->usecase;
1765 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001766 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 uc_info->devices = in->device;
1768 uc_info->in_snd_device = SND_DEVICE_NONE;
1769 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001771 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301772 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1773 adev->perf_lock_opts,
1774 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301777 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1778 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001779
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301780 if (audio_extn_cin_attached_usecase(in->usecase)) {
1781 ret = audio_extn_cin_start_input_stream(in);
1782 if (ret)
1783 goto error_open;
1784 else
1785 goto done_open;
1786 }
1787
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001788 unsigned int flags = PCM_IN;
1789 unsigned int pcm_open_retry_count = 0;
1790
1791 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1792 flags |= PCM_MMAP | PCM_NOIRQ;
1793 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001794 } else if (in->realtime) {
1795 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001796 }
1797
1798 while (1) {
1799 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1800 flags, &in->config);
1801 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1802 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1803 if (in->pcm != NULL) {
1804 pcm_close(in->pcm);
1805 in->pcm = NULL;
1806 }
1807 if (pcm_open_retry_count-- == 0) {
1808 ret = -EIO;
1809 goto error_open;
1810 }
1811 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1812 continue;
1813 }
1814 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001816
1817 ALOGV("%s: pcm_prepare", __func__);
1818 ret = pcm_prepare(in->pcm);
1819 if (ret < 0) {
1820 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1821 pcm_close(in->pcm);
1822 in->pcm = NULL;
1823 goto error_open;
1824 }
1825
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001826 register_in_stream(in);
1827 if (in->realtime) {
1828 ret = pcm_start(in->pcm);
1829 if (ret < 0)
1830 goto error_open;
1831 }
1832
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301833done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301834 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001835 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001836
Eric Laurentc8400632013-02-14 19:04:54 -08001837 return ret;
1838
1839error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301840 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001842error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301843 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301844 /*
1845 * sleep 50ms to allow sufficient time for kernel
1846 * drivers to recover incases like SSR.
1847 */
1848 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001849 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001850
1851 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852}
1853
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001854void lock_input_stream(struct stream_in *in)
1855{
1856 pthread_mutex_lock(&in->pre_lock);
1857 pthread_mutex_lock(&in->lock);
1858 pthread_mutex_unlock(&in->pre_lock);
1859}
1860
1861void lock_output_stream(struct stream_out *out)
1862{
1863 pthread_mutex_lock(&out->pre_lock);
1864 pthread_mutex_lock(&out->lock);
1865 pthread_mutex_unlock(&out->pre_lock);
1866}
1867
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868/* must be called with out->lock locked */
1869static int send_offload_cmd_l(struct stream_out* out, int command)
1870{
1871 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1872
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001873 if (!cmd) {
1874 ALOGE("failed to allocate mem for command 0x%x", command);
1875 return -ENOMEM;
1876 }
1877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 ALOGVV("%s %d", __func__, command);
1879
1880 cmd->cmd = command;
1881 list_add_tail(&out->offload_cmd_list, &cmd->node);
1882 pthread_cond_signal(&out->offload_cond);
1883 return 0;
1884}
1885
1886/* must be called iwth out->lock locked */
1887static void stop_compressed_output_l(struct stream_out *out)
1888{
1889 out->offload_state = OFFLOAD_STATE_IDLE;
1890 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892 if (out->compr != NULL) {
1893 compress_stop(out->compr);
1894 while (out->offload_thread_blocked) {
1895 pthread_cond_wait(&out->cond, &out->lock);
1896 }
1897 }
1898}
1899
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001900bool is_offload_usecase(audio_usecase_t uc_id)
1901{
1902 unsigned int i;
1903 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1904 if (uc_id == offload_usecases[i])
1905 return true;
1906 }
1907 return false;
1908}
1909
vivek mehta446c3962015-09-14 10:57:35 -07001910static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001911{
vivek mehta446c3962015-09-14 10:57:35 -07001912 audio_usecase_t ret_uc = USECASE_INVALID;
1913 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001914 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001915 if (!adev->multi_offload_enable) {
1916 if (is_direct_pcm)
1917 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1918 else
1919 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001920
vivek mehta446c3962015-09-14 10:57:35 -07001921 pthread_mutex_lock(&adev->lock);
1922 if (get_usecase_from_list(adev, ret_uc) != NULL)
1923 ret_uc = USECASE_INVALID;
1924 pthread_mutex_unlock(&adev->lock);
1925
1926 return ret_uc;
1927 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001928
1929 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001930 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1931 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1932 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1933 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001934 break;
1935 }
1936 }
vivek mehta446c3962015-09-14 10:57:35 -07001937
1938 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1939 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001940}
1941
1942static void free_offload_usecase(struct audio_device *adev,
1943 audio_usecase_t uc_id)
1944{
vivek mehta446c3962015-09-14 10:57:35 -07001945 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001946 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001947
1948 if (!adev->multi_offload_enable)
1949 return;
1950
1951 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1952 if (offload_usecases[offload_uc_index] == uc_id) {
1953 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001954 break;
1955 }
1956 }
1957 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1958}
1959
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960static void *offload_thread_loop(void *context)
1961{
1962 struct stream_out *out = (struct stream_out *) context;
1963 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001964 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1967 set_sched_policy(0, SP_FOREGROUND);
1968 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1969
1970 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001971 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 for (;;) {
1973 struct offload_cmd *cmd = NULL;
1974 stream_callback_event_t event;
1975 bool send_callback = false;
1976
1977 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1978 __func__, list_empty(&out->offload_cmd_list),
1979 out->offload_state);
1980 if (list_empty(&out->offload_cmd_list)) {
1981 ALOGV("%s SLEEPING", __func__);
1982 pthread_cond_wait(&out->offload_cond, &out->lock);
1983 ALOGV("%s RUNNING", __func__);
1984 continue;
1985 }
1986
1987 item = list_head(&out->offload_cmd_list);
1988 cmd = node_to_item(item, struct offload_cmd, node);
1989 list_remove(item);
1990
1991 ALOGVV("%s STATE %d CMD %d out->compr %p",
1992 __func__, out->offload_state, cmd->cmd, out->compr);
1993
1994 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1995 free(cmd);
1996 break;
1997 }
1998
1999 if (out->compr == NULL) {
2000 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002001 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002002 pthread_cond_signal(&out->cond);
2003 continue;
2004 }
2005 out->offload_thread_blocked = true;
2006 pthread_mutex_unlock(&out->lock);
2007 send_callback = false;
2008 switch(cmd->cmd) {
2009 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002010 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002012 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 send_callback = true;
2014 event = STREAM_CBK_EVENT_WRITE_READY;
2015 break;
2016 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002017 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302018 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002019 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302020 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002021 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302022 if (ret < 0)
2023 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302024 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302025 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002026 compress_drain(out->compr);
2027 else
2028 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302029 if (ret != -ENETRESET) {
2030 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302031 pthread_mutex_lock(&out->lock);
2032 out->send_new_metadata = 1;
2033 out->send_next_track_params = true;
2034 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302035 event = STREAM_CBK_EVENT_DRAIN_READY;
2036 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2037 } else
2038 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 break;
2040 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002041 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002043 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 send_callback = true;
2045 event = STREAM_CBK_EVENT_DRAIN_READY;
2046 break;
2047 default:
2048 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2049 break;
2050 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002051 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 out->offload_thread_blocked = false;
2053 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002054 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002055 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002057 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 free(cmd);
2059 }
2060
2061 pthread_cond_signal(&out->cond);
2062 while (!list_empty(&out->offload_cmd_list)) {
2063 item = list_head(&out->offload_cmd_list);
2064 list_remove(item);
2065 free(node_to_item(item, struct offload_cmd, node));
2066 }
2067 pthread_mutex_unlock(&out->lock);
2068
2069 return NULL;
2070}
2071
2072static int create_offload_callback_thread(struct stream_out *out)
2073{
2074 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2075 list_init(&out->offload_cmd_list);
2076 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2077 offload_thread_loop, out);
2078 return 0;
2079}
2080
2081static int destroy_offload_callback_thread(struct stream_out *out)
2082{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002083 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084 stop_compressed_output_l(out);
2085 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2086
2087 pthread_mutex_unlock(&out->lock);
2088 pthread_join(out->offload_thread, (void **) NULL);
2089 pthread_cond_destroy(&out->offload_cond);
2090
2091 return 0;
2092}
2093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094static int stop_output_stream(struct stream_out *out)
2095{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302096 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097 struct audio_usecase *uc_info;
2098 struct audio_device *adev = out->dev;
2099
Eric Laurent994a6932013-07-17 11:51:42 -07002100 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002101 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 uc_info = get_usecase_from_list(adev, out->usecase);
2103 if (uc_info == NULL) {
2104 ALOGE("%s: Could not find the usecase (%d) in the list",
2105 __func__, out->usecase);
2106 return -EINVAL;
2107 }
2108
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002109 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302110 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002111 if (adev->visualizer_stop_output != NULL)
2112 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002113
2114 audio_extn_dts_remove_state_notifier_node(out->usecase);
2115
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002116 if (adev->offload_effects_stop_output != NULL)
2117 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2118 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002119
Eric Laurent150dbfe2013-02-27 14:31:02 -08002120 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002121 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002122
2123 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002124 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002126 list_remove(&uc_info->list);
2127 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302130 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002131 ALOGV("Disable passthrough , reset mixer to pcm");
2132 /* NO_PASSTHROUGH */
2133 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002134 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002135 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2136 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002137
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302138 /* Must be called after removing the usecase from list */
2139 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302140 audio_extn_keep_alive_start();
2141
Eric Laurent994a6932013-07-17 11:51:42 -07002142 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 return ret;
2144}
2145
2146int start_output_stream(struct stream_out *out)
2147{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 struct audio_usecase *uc_info;
2150 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302151 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002153 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2154 ret = -EINVAL;
2155 goto error_config;
2156 }
2157
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302158 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2159 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2160 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302161
Naresh Tanniru80659832014-06-04 18:17:56 +05302162 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302163 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302164 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165 goto error_config;
2166 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302167
Eric Laurentb23d5282013-05-14 15:27:20 -07002168 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 if (out->pcm_device_id < 0) {
2170 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2171 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002172 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002173 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 }
2175
2176 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002177
2178 if (!uc_info) {
2179 ret = -ENOMEM;
2180 goto error_config;
2181 }
2182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 uc_info->id = out->usecase;
2184 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002185 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002186 uc_info->devices = out->devices;
2187 uc_info->in_snd_device = SND_DEVICE_NONE;
2188 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002189 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302191 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2192 adev->perf_lock_opts,
2193 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302194
2195 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2196 audio_extn_keep_alive_stop();
2197 if (audio_extn_passthru_is_enabled() &&
2198 audio_extn_passthru_is_passthrough_stream(out)) {
2199 audio_extn_passthru_on_start(out);
2200 audio_extn_passthru_update_stream_configuration(adev, out);
2201 }
2202 }
2203
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002204 select_devices(adev, out->usecase);
2205
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002206 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2207 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002208 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002209 unsigned int flags = PCM_OUT;
2210 unsigned int pcm_open_retry_count = 0;
2211 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2212 flags |= PCM_MMAP | PCM_NOIRQ;
2213 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002214 } else if (out->realtime) {
2215 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002216 } else
2217 flags |= PCM_MONOTONIC;
2218
2219 while (1) {
2220 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2221 flags, &out->config);
2222 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2223 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2224 if (out->pcm != NULL) {
2225 pcm_close(out->pcm);
2226 out->pcm = NULL;
2227 }
2228 if (pcm_open_retry_count-- == 0) {
2229 ret = -EIO;
2230 goto error_open;
2231 }
2232 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2233 continue;
2234 }
2235 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002236 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002237
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002238 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2239 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002240
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002241 ALOGV("%s: pcm_prepare", __func__);
2242 if (pcm_is_ready(out->pcm)) {
2243 ret = pcm_prepare(out->pcm);
2244 if (ret < 0) {
2245 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2246 pcm_close(out->pcm);
2247 out->pcm = NULL;
2248 goto error_open;
2249 }
2250 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002252 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2253 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002255 out->compr = compress_open(adev->snd_card,
2256 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 COMPRESS_IN, &out->compr_config);
2258 if (out->compr && !is_compress_ready(out->compr)) {
2259 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2260 compress_close(out->compr);
2261 out->compr = NULL;
2262 ret = -EIO;
2263 goto error_open;
2264 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302265 /* compress_open sends params of the track, so reset the flag here */
2266 out->is_compr_metadata_avail = false;
2267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 if (out->offload_callback)
2269 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002270
Fred Oh3f43e742015-03-04 18:42:34 -08002271 /* Since small bufs uses blocking writes, a write will be blocked
2272 for the default max poll time (20s) in the event of an SSR.
2273 Reduce the poll time to observe and deal with SSR faster.
2274 */
Ashish Jain5106d362016-05-11 19:23:33 +05302275 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002276 compress_set_max_poll_wait(out->compr, 1000);
2277 }
2278
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002279 audio_extn_dts_create_state_notifier_node(out->usecase);
2280 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2281 popcount(out->channel_mask),
2282 out->playback_started);
2283
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002284#ifdef DS1_DOLBY_DDP_ENABLED
2285 if (audio_extn_is_dolby_format(out->format))
2286 audio_extn_dolby_send_ddp_endp_params(adev);
2287#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302288 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002289 if (adev->visualizer_start_output != NULL)
2290 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2291 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302292 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002293 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002296
2297 if (ret == 0) {
2298 register_out_stream(out);
2299 if (out->realtime) {
2300 ret = pcm_start(out->pcm);
2301 if (ret < 0)
2302 goto error_open;
2303 }
2304 }
2305
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302306 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002307 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002308
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002309 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302311 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002313error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302314 /*
2315 * sleep 50ms to allow sufficient time for kernel
2316 * drivers to recover incases like SSR.
2317 */
2318 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320}
2321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322static int check_input_parameters(uint32_t sample_rate,
2323 audio_format_t format,
2324 int channel_count)
2325{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002326 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302328 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2329 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2330 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002331 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302332 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002333
2334 switch (channel_count) {
2335 case 1:
2336 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302337 case 3:
2338 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002339 case 6:
2340 break;
2341 default:
2342 ret = -EINVAL;
2343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
2345 switch (sample_rate) {
2346 case 8000:
2347 case 11025:
2348 case 12000:
2349 case 16000:
2350 case 22050:
2351 case 24000:
2352 case 32000:
2353 case 44100:
2354 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302355 case 96000:
2356 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 break;
2358 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002359 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 }
2361
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002362 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363}
2364
2365static size_t get_input_buffer_size(uint32_t sample_rate,
2366 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002367 int channel_count,
2368 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 size_t size = 0;
2371
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002372 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2373 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002375 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002376 if (is_low_latency)
2377 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302378
2379 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002381 /* make sure the size is multiple of 32 bytes
2382 * At 48 kHz mono 16-bit PCM:
2383 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2384 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2385 */
2386 size += 0x1f;
2387 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002388
2389 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390}
2391
Ashish Jain058165c2016-09-28 23:18:48 +05302392static size_t get_output_period_size(uint32_t sample_rate,
2393 audio_format_t format,
2394 int channel_count,
2395 int duration /*in millisecs*/)
2396{
2397 size_t size = 0;
2398 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2399
2400 if ((duration == 0) || (sample_rate == 0) ||
2401 (bytes_per_sample == 0) || (channel_count == 0)) {
2402 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2403 bytes_per_sample, channel_count);
2404 return -EINVAL;
2405 }
2406
2407 size = (sample_rate *
2408 duration *
2409 bytes_per_sample *
2410 channel_count) / 1000;
2411 /*
2412 * To have same PCM samples for all channels, the buffer size requires to
2413 * be multiple of (number of channels * bytes per sample)
2414 * For writes to succeed, the buffer must be written at address which is multiple of 32
2415 */
2416 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2417
2418 return (size/(channel_count * bytes_per_sample));
2419}
2420
Ashish Jain5106d362016-05-11 19:23:33 +05302421static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2422{
2423 uint64_t actual_frames_rendered = 0;
2424 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2425
2426 /* This adjustment accounts for buffering after app processor.
2427 * It is based on estimated DSP latency per use case, rather than exact.
2428 */
2429 int64_t platform_latency = platform_render_latency(out->usecase) *
2430 out->sample_rate / 1000000LL;
2431
2432 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2433 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2434 * hence only estimate.
2435 */
2436 int64_t signed_frames = out->written - kernel_buffer_size;
2437
2438 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2439
2440 if (signed_frames > 0)
2441 actual_frames_rendered = signed_frames;
2442
2443 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2444 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2445 (long long int)out->written, (int)kernel_buffer_size,
2446 audio_bytes_per_sample(out->compr_config.codec->format),
2447 popcount(out->channel_mask));
2448
2449 return actual_frames_rendered;
2450}
2451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2453{
2454 struct stream_out *out = (struct stream_out *)stream;
2455
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457}
2458
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002459static int out_set_sample_rate(struct audio_stream *stream __unused,
2460 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461{
2462 return -ENOSYS;
2463}
2464
2465static size_t out_get_buffer_size(const struct audio_stream *stream)
2466{
2467 struct stream_out *out = (struct stream_out *)stream;
2468
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002469 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002471 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2472 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302473 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302474 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002476 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002477 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478}
2479
2480static uint32_t out_get_channels(const struct audio_stream *stream)
2481{
2482 struct stream_out *out = (struct stream_out *)stream;
2483
2484 return out->channel_mask;
2485}
2486
2487static audio_format_t out_get_format(const struct audio_stream *stream)
2488{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 struct stream_out *out = (struct stream_out *)stream;
2490
2491 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492}
2493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002494static int out_set_format(struct audio_stream *stream __unused,
2495 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496{
2497 return -ENOSYS;
2498}
2499
2500static int out_standby(struct audio_stream *stream)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002504
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302505 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2506 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002508 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002510 if (adev->adm_deregister_stream)
2511 adev->adm_deregister_stream(adev->adm_data, out->handle);
2512
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002513 if (is_offload_usecase(out->usecase))
2514 stop_compressed_output_l(out);
2515
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002516 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002518 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2519 voice_extn_compress_voip_close_output_stream(stream);
2520 pthread_mutex_unlock(&adev->lock);
2521 pthread_mutex_unlock(&out->lock);
2522 ALOGD("VOIP output entered standby");
2523 return 0;
2524 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002525 if (out->pcm) {
2526 pcm_close(out->pcm);
2527 out->pcm = NULL;
2528 }
2529 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002530 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302531 out->send_next_track_params = false;
2532 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002533 out->gapless_mdata.encoder_delay = 0;
2534 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 if (out->compr != NULL) {
2536 compress_close(out->compr);
2537 out->compr = NULL;
2538 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002541 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 }
2543 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302544 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 return 0;
2546}
2547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002548static int out_dump(const struct audio_stream *stream __unused,
2549 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550{
2551 return 0;
2552}
2553
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002554static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2555{
2556 int ret = 0;
2557 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002558
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002559 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002560 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002561 return -EINVAL;
2562 }
2563
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302564 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002565
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002566 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2567 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302568 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002569 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002570 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2571 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302572 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002573 }
2574
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002575 ALOGV("%s new encoder delay %u and padding %u", __func__,
2576 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2577
2578 return 0;
2579}
2580
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002581static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2582{
2583 return out == adev->primary_output || out == adev->voice_tx_output;
2584}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2587{
2588 struct stream_out *out = (struct stream_out *)stream;
2589 struct audio_device *adev = out->dev;
2590 struct str_parms *parms;
2591 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002592 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
sangwoobc677242013-08-08 16:53:43 +09002594 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002595 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302597 if (!parms)
2598 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002599 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2600 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002602 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002603 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002605 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002606 * When HDMI cable is unplugged the music playback is paused and
2607 * the policy manager sends routing=0. But the audioflinger continues
2608 * to write data until standby time (3sec). As the HDMI core is
2609 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002610 * Avoid this by routing audio to speaker until standby.
2611 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002612 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2613 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302614 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002615 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2616 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002617 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302618 /*
2619 * When A2DP is disconnected the
2620 * music playback is paused and the policy manager sends routing=0
2621 * But the audioflingercontinues to write data until standby time
2622 * (3sec). As BT is turned off, the write gets blocked.
2623 * Avoid this by routing audio to speaker until standby.
2624 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002625 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302626 (val == AUDIO_DEVICE_NONE)) {
2627 val = AUDIO_DEVICE_OUT_SPEAKER;
2628 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302629 /* To avoid a2dp to sco overlapping force route BT usecases
2630 * to speaker based on Phone state
2631 */
Ashish Jainc597d102016-12-12 10:31:34 +05302632 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2633 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2634 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2635 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302636 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2637 (adev->mode == AUDIO_MODE_IN_CALL))) {
2638 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2639 val = AUDIO_DEVICE_OUT_SPEAKER;
2640 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002641 /*
2642 * select_devices() call below switches all the usecases on the same
2643 * backend to the new device. Refer to check_usecases_codec_backend() in
2644 * the select_devices(). But how do we undo this?
2645 *
2646 * For example, music playback is active on headset (deep-buffer usecase)
2647 * and if we go to ringtones and select a ringtone, low-latency usecase
2648 * will be started on headset+speaker. As we can't enable headset+speaker
2649 * and headset devices at the same time, select_devices() switches the music
2650 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2651 * So when the ringtone playback is completed, how do we undo the same?
2652 *
2653 * We are relying on the out_set_parameters() call on deep-buffer output,
2654 * once the ringtone playback is ended.
2655 * NOTE: We should not check if the current devices are same as new devices.
2656 * Because select_devices() must be called to switch back the music
2657 * playback to headset.
2658 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002659 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002660 audio_devices_t new_dev = val;
2661 bool same_dev = out->devices == new_dev;
2662 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002663
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002664 if (output_drives_call(adev, out)) {
2665 if(!voice_is_in_call(adev)) {
2666 if (adev->mode == AUDIO_MODE_IN_CALL) {
2667 adev->current_call_output = out;
2668 ret = voice_start_call(adev);
2669 }
2670 } else {
2671 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002672 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002673 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002674 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002675
2676 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002677 if (!same_dev) {
2678 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302679 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2680 adev->perf_lock_opts,
2681 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002682 if (adev->adm_on_routing_change)
2683 adev->adm_on_routing_change(adev->adm_data,
2684 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002685 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002686 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302687 if (!same_dev)
2688 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002689 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002690 }
2691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002693 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002695
2696 if (out == adev->primary_output) {
2697 pthread_mutex_lock(&adev->lock);
2698 audio_extn_set_parameters(adev, parms);
2699 pthread_mutex_unlock(&adev->lock);
2700 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002701 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002702 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002703 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002704
2705 audio_extn_dts_create_state_notifier_node(out->usecase);
2706 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2707 popcount(out->channel_mask),
2708 out->playback_started);
2709
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002710 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002711 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002712
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302713 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2714 if (err >= 0) {
2715 strlcpy(out->profile, value, sizeof(out->profile));
2716 ALOGV("updating stream profile with value '%s'", out->profile);
2717 lock_output_stream(out);
2718 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2719 &adev->streams_output_cfg_list,
2720 out->devices, out->flags, out->format,
2721 out->sample_rate, out->bit_width,
2722 out->channel_mask, out->profile,
2723 &out->app_type_cfg);
2724 pthread_mutex_unlock(&out->lock);
2725 }
2726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302728error:
Eric Laurent994a6932013-07-17 11:51:42 -07002729 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 return ret;
2731}
2732
2733static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2734{
2735 struct stream_out *out = (struct stream_out *)stream;
2736 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002737 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 char value[256];
2739 struct str_parms *reply = str_parms_create();
2740 size_t i, j;
2741 int ret;
2742 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002743
2744 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002745 if (reply) {
2746 str_parms_destroy(reply);
2747 }
2748 if (query) {
2749 str_parms_destroy(query);
2750 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002751 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2752 return NULL;
2753 }
2754
Eric Laurent994a6932013-07-17 11:51:42 -07002755 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2757 if (ret >= 0) {
2758 value[0] = '\0';
2759 i = 0;
2760 while (out->supported_channel_masks[i] != 0) {
2761 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2762 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2763 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002764 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002766 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 first = false;
2768 break;
2769 }
2770 }
2771 i++;
2772 }
2773 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2774 str = str_parms_to_str(reply);
2775 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002776 voice_extn_out_get_parameters(out, query, reply);
2777 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002778 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002779 free(str);
2780 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002783
Alexy Joseph62142aa2015-11-16 15:10:34 -08002784
2785 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2786 if (ret >= 0) {
2787 value[0] = '\0';
2788 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2789 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302790 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002791 } else {
2792 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302793 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002794 }
2795 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002796 if (str)
2797 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002798 str = str_parms_to_str(reply);
2799 }
2800
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002801 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2802 if (ret >= 0) {
2803 value[0] = '\0';
2804 i = 0;
2805 first = true;
2806 while (out->supported_formats[i] != 0) {
2807 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2808 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2809 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002810 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002811 }
2812 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2813 first = false;
2814 break;
2815 }
2816 }
2817 i++;
2818 }
2819 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002820 if (str)
2821 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002822 str = str_parms_to_str(reply);
2823 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002824
2825 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2826 if (ret >= 0) {
2827 value[0] = '\0';
2828 i = 0;
2829 first = true;
2830 while (out->supported_sample_rates[i] != 0) {
2831 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2832 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2833 if (!first) {
2834 strlcat(value, "|", sizeof(value));
2835 }
2836 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2837 first = false;
2838 break;
2839 }
2840 }
2841 i++;
2842 }
2843 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2844 if (str)
2845 free(str);
2846 str = str_parms_to_str(reply);
2847 }
2848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 str_parms_destroy(query);
2850 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002851 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 return str;
2853}
2854
2855static uint32_t out_get_latency(const struct audio_stream_out *stream)
2856{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002857 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002859 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860
Alexy Josephaa54c872014-12-03 02:46:47 -08002861 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002862 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002863 } else if (out->realtime) {
2864 // since the buffer won't be filled up faster than realtime,
2865 // return a smaller number
2866 if (out->config.rate)
2867 period_ms = (out->af_period_multiplier * out->config.period_size *
2868 1000) / (out->config.rate);
2869 else
2870 period_ms = 0;
2871 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002872 } else {
2873 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002875 }
2876
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302877 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002878 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879}
2880
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302881static float AmpToDb(float amplification)
2882{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302883 float db = DSD_VOLUME_MIN_DB;
2884 if (amplification > 0) {
2885 db = 20 * log10(amplification);
2886 if(db < DSD_VOLUME_MIN_DB)
2887 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302888 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302889 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302890}
2891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892static int out_set_volume(struct audio_stream_out *stream, float left,
2893 float right)
2894{
Eric Laurenta9024de2013-04-04 09:19:12 -07002895 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 int volume[2];
2897
Eric Laurenta9024de2013-04-04 09:19:12 -07002898 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2899 /* only take left channel into account: the API is for stereo anyway */
2900 out->muted = (left == 0.0f);
2901 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002902 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302903 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002904 /*
2905 * Set mute or umute on HDMI passthrough stream.
2906 * Only take left channel into account.
2907 * Mute is 0 and unmute 1
2908 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302909 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302910 } else if (out->format == AUDIO_FORMAT_DSD){
2911 char mixer_ctl_name[128] = "DSD Volume";
2912 struct audio_device *adev = out->dev;
2913 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2914
2915 if (!ctl) {
2916 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2917 __func__, mixer_ctl_name);
2918 return -EINVAL;
2919 }
2920 volume[0] = (int)(AmpToDb(left));
2921 volume[1] = (int)(AmpToDb(right));
2922 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2923 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002924 } else {
2925 char mixer_ctl_name[128];
2926 struct audio_device *adev = out->dev;
2927 struct mixer_ctl *ctl;
2928 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002929 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002931 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2932 "Compress Playback %d Volume", pcm_device_id);
2933 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2934 if (!ctl) {
2935 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2936 __func__, mixer_ctl_name);
2937 return -EINVAL;
2938 }
2939 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2940 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2941 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2942 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002944 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 return -ENOSYS;
2947}
2948
2949static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2950 size_t bytes)
2951{
2952 struct stream_out *out = (struct stream_out *)stream;
2953 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302954 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002955 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002957 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302958
Naresh Tanniru80659832014-06-04 18:17:56 +05302959 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002960
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302961 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302962 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302963 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2964 pthread_mutex_unlock(&out->lock);
2965 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302966 } else {
2967 /* increase written size during SSR to avoid mismatch
2968 * with the written frames count in AF
2969 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002970 // bytes per frame
2971 size_t bpf = audio_bytes_per_sample(out->format) *
2972 audio_channel_count_from_out_mask(out->channel_mask);
2973 if (bpf != 0)
2974 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302975 ALOGD(" %s: sound card is not active/SSR state", __func__);
2976 ret= -EIO;
2977 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302978 }
2979 }
2980
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302981 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302982 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2983 if (audio_bytes_per_sample(out->format) != 0)
2984 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2985 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302986 goto exit;
2987 }
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002990 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002991 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2993 ret = voice_extn_compress_voip_start_output_stream(out);
2994 else
2995 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002996 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002999 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 goto exit;
3001 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003002
3003 if (last_known_cal_step != -1) {
3004 ALOGD("%s: retry previous failed cal level set", __func__);
3005 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Ashish Jain81eb2a82015-05-13 10:52:34 +05303009 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003010 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303011 adev->is_channel_status_set = true;
3012 }
3013
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003014 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003015 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003016 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003017 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003018 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3019 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303020 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3021 ALOGD("copl(%p):send next track params in gapless", out);
3022 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3023 out->send_next_track_params = false;
3024 out->is_compr_metadata_avail = false;
3025 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003026 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303027 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303028 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003029
Ashish Jain83a6cc22016-06-28 14:34:17 +05303030 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303031 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303032 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303033 pthread_mutex_unlock(&out->lock);
3034 return -EINVAL;
3035 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303036 audio_format_t dst_format = out->hal_op_format;
3037 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303038
3039 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3040 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3041
Ashish Jain83a6cc22016-06-28 14:34:17 +05303042 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303043 dst_format,
3044 buffer,
3045 src_format,
3046 frames);
3047
Ashish Jain83a6cc22016-06-28 14:34:17 +05303048 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303049 bytes_to_write);
3050
3051 /*Convert written bytes in audio flinger format*/
3052 if (ret > 0)
3053 ret = ((ret * format_to_bitwidth_table[out->format]) /
3054 format_to_bitwidth_table[dst_format]);
3055 }
3056 } else
3057 ret = compress_write(out->compr, buffer, bytes);
3058
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303059 if (ret < 0)
3060 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303061 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303062 /*msg to cb thread only if non blocking write is enabled*/
3063 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303064 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303066 } else if (-ENETRESET == ret) {
3067 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3068 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3069 pthread_mutex_unlock(&out->lock);
3070 out_standby(&out->stream.common);
3071 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 }
Ashish Jain5106d362016-05-11 19:23:33 +05303073 if ( ret == (ssize_t)bytes && !out->non_blocking)
3074 out->written += bytes;
3075
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303076 /* Call compr start only when non-zero bytes of data is there to be rendered */
3077 if (!out->playback_started && ret > 0) {
3078 int status = compress_start(out->compr);
3079 if (status < 0) {
3080 ret = status;
3081 ALOGE("%s: compr start failed with err %d", __func__, errno);
3082 goto exit;
3083 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003084 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 out->playback_started = 1;
3086 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003087
3088 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3089 popcount(out->channel_mask),
3090 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 }
3092 pthread_mutex_unlock(&out->lock);
3093 return ret;
3094 } else {
3095 if (out->pcm) {
3096 if (out->muted)
3097 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003098
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303099 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003100
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003101 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003102
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003103 if (out->config.rate)
3104 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3105 out->config.rate;
3106
3107 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3108
3109 request_out_focus(out, ns);
3110
3111 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003112 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003113 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303114 out->convert_buffer != NULL) {
3115
3116 memcpy_by_audio_format(out->convert_buffer,
3117 out->hal_op_format,
3118 buffer,
3119 out->hal_ip_format,
3120 out->config.period_size * out->config.channels);
3121
3122 ret = pcm_write(out->pcm, out->convert_buffer,
3123 (out->config.period_size *
3124 out->config.channels *
3125 format_to_bitwidth_table[out->hal_op_format]));
3126 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003127 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303128 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003129
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003130 release_out_focus(out);
3131
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303132 if (ret < 0)
3133 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303134 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3135 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3136 else
3137 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 }
3140
3141exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303142 /* ToDo: There may be a corner case when SSR happens back to back during
3143 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303146 }
3147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 pthread_mutex_unlock(&out->lock);
3149
3150 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003151 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003152 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303153 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303154 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303155 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303156 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303157 out->standby = true;
3158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303160 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3161 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3162 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 }
3164 return bytes;
3165}
3166
3167static int out_get_render_position(const struct audio_stream_out *stream,
3168 uint32_t *dsp_frames)
3169{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303171 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003172
3173 if (dsp_frames == NULL)
3174 return -EINVAL;
3175
3176 *dsp_frames = 0;
3177 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003178 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303179
3180 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3181 * this operation and adev_close_output_stream(where out gets reset).
3182 */
3183 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3184 *dsp_frames = get_actual_pcm_frames_rendered(out);
3185 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3186 return 0;
3187 }
3188
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003189 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303190 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303191 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303193 if (ret < 0)
3194 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003195 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303196 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 }
3198 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303199 if (-ENETRESET == ret) {
3200 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3201 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3202 return -EINVAL;
3203 } else if(ret < 0) {
3204 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3205 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303206 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3207 /*
3208 * Handle corner case where compress session is closed during SSR
3209 * and timestamp is queried
3210 */
3211 ALOGE(" ERROR: sound card not active, return error");
3212 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303213 } else {
3214 return 0;
3215 }
Zhou Song32a556e2015-05-05 10:46:56 +08003216 } else if (audio_is_linear_pcm(out->format)) {
3217 *dsp_frames = out->written;
3218 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219 } else
3220 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221}
3222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003223static int out_add_audio_effect(const struct audio_stream *stream __unused,
3224 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225{
3226 return 0;
3227}
3228
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003229static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3230 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231{
3232 return 0;
3233}
3234
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003235static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3236 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237{
3238 return -EINVAL;
3239}
3240
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003241static int out_get_presentation_position(const struct audio_stream_out *stream,
3242 uint64_t *frames, struct timespec *timestamp)
3243{
3244 struct stream_out *out = (struct stream_out *)stream;
3245 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003246 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003247
Ashish Jain5106d362016-05-11 19:23:33 +05303248 /* below piece of code is not guarded against any lock because audioFliner serializes
3249 * this operation and adev_close_output_stream( where out gets reset).
3250 */
3251 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3252 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3253 *frames = get_actual_pcm_frames_rendered(out);
3254 /* this is the best we can do */
3255 clock_gettime(CLOCK_MONOTONIC, timestamp);
3256 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3257 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3258 return 0;
3259 }
3260
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003261 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003262
Ashish Jain5106d362016-05-11 19:23:33 +05303263 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3264 ret = compress_get_tstamp(out->compr, &dsp_frames,
3265 &out->sample_rate);
3266 ALOGVV("%s rendered frames %ld sample_rate %d",
3267 __func__, dsp_frames, out->sample_rate);
3268 *frames = dsp_frames;
3269 if (ret < 0)
3270 ret = -errno;
3271 if (-ENETRESET == ret) {
3272 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3273 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3274 ret = -EINVAL;
3275 } else
3276 ret = 0;
3277 /* this is the best we can do */
3278 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003279 } else {
3280 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003281 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003282 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3283 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003284 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003285 // This adjustment accounts for buffering after app processor.
3286 // It is based on estimated DSP latency per use case, rather than exact.
3287 signed_frames -=
3288 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3289
Eric Laurent949a0892013-09-20 09:20:13 -07003290 // It would be unusual for this value to be negative, but check just in case ...
3291 if (signed_frames >= 0) {
3292 *frames = signed_frames;
3293 ret = 0;
3294 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003295 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303296 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3297 *frames = out->written;
3298 clock_gettime(CLOCK_MONOTONIC, timestamp);
3299 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003300 }
3301 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003302 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003303 return ret;
3304}
3305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003306static int out_set_callback(struct audio_stream_out *stream,
3307 stream_callback_t callback, void *cookie)
3308{
3309 struct stream_out *out = (struct stream_out *)stream;
3310
3311 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003312 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003313 out->offload_callback = callback;
3314 out->offload_cookie = cookie;
3315 pthread_mutex_unlock(&out->lock);
3316 return 0;
3317}
3318
3319static int out_pause(struct audio_stream_out* stream)
3320{
3321 struct stream_out *out = (struct stream_out *)stream;
3322 int status = -ENOSYS;
3323 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003324 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003325 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003326 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303328 struct audio_device *adev = out->dev;
3329 int snd_scard_state = get_snd_card_state(adev);
3330
3331 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3332 status = compress_pause(out->compr);
3333
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003335
Mingming Yin21854652016-04-13 11:54:02 -07003336 if (audio_extn_passthru_is_active()) {
3337 ALOGV("offload use case, pause passthru");
3338 audio_extn_passthru_on_pause(out);
3339 }
3340
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303341 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003342 audio_extn_dts_notify_playback_state(out->usecase, 0,
3343 out->sample_rate, popcount(out->channel_mask),
3344 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003345 }
3346 pthread_mutex_unlock(&out->lock);
3347 }
3348 return status;
3349}
3350
3351static int out_resume(struct audio_stream_out* stream)
3352{
3353 struct stream_out *out = (struct stream_out *)stream;
3354 int status = -ENOSYS;
3355 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003356 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003357 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003359 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303361 struct audio_device *adev = out->dev;
3362 int snd_scard_state = get_snd_card_state(adev);
3363
Mingming Yin21854652016-04-13 11:54:02 -07003364 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3365 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3366 pthread_mutex_lock(&out->dev->lock);
3367 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003368 pthread_mutex_unlock(&out->dev->lock);
3369 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303370 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003371 }
3372 if (!status) {
3373 out->offload_state = OFFLOAD_STATE_PLAYING;
3374 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303375 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003376 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3377 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 }
3379 pthread_mutex_unlock(&out->lock);
3380 }
3381 return status;
3382}
3383
3384static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3385{
3386 struct stream_out *out = (struct stream_out *)stream;
3387 int status = -ENOSYS;
3388 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003389 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003390 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003391 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3392 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3393 else
3394 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3395 pthread_mutex_unlock(&out->lock);
3396 }
3397 return status;
3398}
3399
3400static int out_flush(struct audio_stream_out* stream)
3401{
3402 struct stream_out *out = (struct stream_out *)stream;
3403 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003404 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003405 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003406 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003407 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3408 stop_compressed_output_l(out);
3409 out->written = 0;
3410 } else {
3411 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3412 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003413 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003414 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003415 return 0;
3416 }
3417 return -ENOSYS;
3418}
3419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420/** audio_stream_in implementation **/
3421static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3422{
3423 struct stream_in *in = (struct stream_in *)stream;
3424
3425 return in->config.rate;
3426}
3427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003428static int in_set_sample_rate(struct audio_stream *stream __unused,
3429 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430{
3431 return -ENOSYS;
3432}
3433
3434static size_t in_get_buffer_size(const struct audio_stream *stream)
3435{
3436 struct stream_in *in = (struct stream_in *)stream;
3437
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003438 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3439 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003440 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3441 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303442 else if(audio_extn_cin_attached_usecase(in->usecase))
3443 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003444
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003445 return in->config.period_size * in->af_period_multiplier *
3446 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447}
3448
3449static uint32_t in_get_channels(const struct audio_stream *stream)
3450{
3451 struct stream_in *in = (struct stream_in *)stream;
3452
3453 return in->channel_mask;
3454}
3455
3456static audio_format_t in_get_format(const struct audio_stream *stream)
3457{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003458 struct stream_in *in = (struct stream_in *)stream;
3459
3460 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461}
3462
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003463static int in_set_format(struct audio_stream *stream __unused,
3464 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465{
3466 return -ENOSYS;
3467}
3468
3469static int in_standby(struct audio_stream *stream)
3470{
3471 struct stream_in *in = (struct stream_in *)stream;
3472 struct audio_device *adev = in->dev;
3473 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303474 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3475 stream, in->usecase, use_case_table[in->usecase]);
3476
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003477 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003478 if (!in->standby && in->is_st_session) {
3479 ALOGD("%s: sound trigger pcm stop lab", __func__);
3480 audio_extn_sound_trigger_stop_lab(in);
3481 in->standby = 1;
3482 }
3483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003485 if (adev->adm_deregister_stream)
3486 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3487
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003488 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003490 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3491 voice_extn_compress_voip_close_input_stream(stream);
3492 ALOGD("VOIP input entered standby");
3493 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303494 if (audio_extn_cin_attached_usecase(in->usecase))
3495 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003496 if (in->pcm) {
3497 pcm_close(in->pcm);
3498 in->pcm = NULL;
3499 }
3500 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003501 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003502 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 }
3504 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003505 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 return status;
3507}
3508
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003509static int in_dump(const struct audio_stream *stream __unused,
3510 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511{
3512 return 0;
3513}
3514
3515static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3516{
3517 struct stream_in *in = (struct stream_in *)stream;
3518 struct audio_device *adev = in->dev;
3519 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003521 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303523 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 parms = str_parms_create_str(kvpairs);
3525
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303526 if (!parms)
3527 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003528 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003529 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003530
3531 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3532 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 val = atoi(value);
3534 /* no audio source uses val == 0 */
3535 if ((in->source != val) && (val != 0)) {
3536 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003537 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3538 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3539 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003540 (in->config.rate == 8000 || in->config.rate == 16000 ||
3541 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003542 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003543 err = voice_extn_compress_voip_open_input_stream(in);
3544 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003545 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003546 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003547 }
3548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 }
3550 }
3551
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003552 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3553 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003555 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 in->device = val;
3557 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003558 if (!in->standby && !in->is_st_session) {
3559 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003560 if (adev->adm_on_routing_change)
3561 adev->adm_on_routing_change(adev->adm_data,
3562 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003563 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 }
3566 }
3567
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303568 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3569 if (err >= 0) {
3570 strlcpy(in->profile, value, sizeof(in->profile));
3571 ALOGV("updating stream profile with value '%s'", in->profile);
3572 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3573 &adev->streams_input_cfg_list,
3574 in->device, in->flags, in->format,
3575 in->sample_rate, in->bit_width,
3576 in->profile, &in->app_type_cfg);
3577 }
3578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003580 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
3582 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303583error:
Eric Laurent994a6932013-07-17 11:51:42 -07003584 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 return ret;
3586}
3587
3588static char* in_get_parameters(const struct audio_stream *stream,
3589 const char *keys)
3590{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003591 struct stream_in *in = (struct stream_in *)stream;
3592 struct str_parms *query = str_parms_create_str(keys);
3593 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003594 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003595
3596 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003597 if (reply) {
3598 str_parms_destroy(reply);
3599 }
3600 if (query) {
3601 str_parms_destroy(query);
3602 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003603 ALOGE("in_get_parameters: failed to create query or reply");
3604 return NULL;
3605 }
3606
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003607 ALOGV("%s: enter: keys - %s", __func__, keys);
3608
3609 voice_extn_in_get_parameters(in, query, reply);
3610
3611 str = str_parms_to_str(reply);
3612 str_parms_destroy(query);
3613 str_parms_destroy(reply);
3614
3615 ALOGV("%s: exit: returns - %s", __func__, str);
3616 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617}
3618
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003619static int in_set_gain(struct audio_stream_in *stream __unused,
3620 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621{
3622 return 0;
3623}
3624
3625static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3626 size_t bytes)
3627{
3628 struct stream_in *in = (struct stream_in *)stream;
3629 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303630 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303631 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303632 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003634 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303635
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003636 if (in->is_st_session) {
3637 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3638 /* Read from sound trigger HAL */
3639 audio_extn_sound_trigger_read(in, buffer, bytes);
3640 pthread_mutex_unlock(&in->lock);
3641 return bytes;
3642 }
3643
Ashish Jainbbce4322016-02-16 13:25:27 +05303644 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003645 ALOGD(" %s: sound card is not active/SSR state", __func__);
3646 ret= -EIO;;
3647 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303648 }
3649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003651 pthread_mutex_lock(&adev->lock);
3652 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3653 ret = voice_extn_compress_voip_start_input_stream(in);
3654 else
3655 ret = start_input_stream(in);
3656 pthread_mutex_unlock(&adev->lock);
3657 if (ret != 0) {
3658 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 }
3660 in->standby = 0;
3661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003663 // what's the duration requested by the client?
3664 long ns = 0;
3665
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303666 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003667 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3668 in->config.rate;
3669
3670 request_in_focus(in, ns);
3671 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003672
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303673 if (audio_extn_cin_attached_usecase(in->usecase)) {
3674 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3675 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303676 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003677 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303678 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003679 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003680 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003681 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303682 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003683 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303684 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3685 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3686 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3687 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303688 ret = -EINVAL;
3689 goto exit;
3690 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303691 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303692 ret = -errno;
3693 }
3694 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303695 /* bytes read is always set to bytes for non compress usecases */
3696 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 }
3698
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003699 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 /*
3702 * Instead of writing zeroes here, we could trust the hardware
3703 * to always provide zeroes when muted.
3704 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303705 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3706 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 memset(buffer, 0, bytes);
3708
3709exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303710 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303711 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003712 if (-ENETRESET == ret)
3713 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 pthread_mutex_unlock(&in->lock);
3716
3717 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303718 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303719 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303720 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303721 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303722 in->standby = true;
3723 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303724 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003726 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303727 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303728 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303730 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731}
3732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003733static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734{
3735 return 0;
3736}
3737
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003738static int add_remove_audio_effect(const struct audio_stream *stream,
3739 effect_handle_t effect,
3740 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003742 struct stream_in *in = (struct stream_in *)stream;
3743 int status = 0;
3744 effect_descriptor_t desc;
3745
3746 status = (*effect)->get_descriptor(effect, &desc);
3747 if (status != 0)
3748 return status;
3749
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003750 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003751 pthread_mutex_lock(&in->dev->lock);
3752 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3753 in->enable_aec != enable &&
3754 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3755 in->enable_aec = enable;
3756 if (!in->standby)
3757 select_devices(in->dev, in->usecase);
3758 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003759 if (in->enable_ns != enable &&
3760 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3761 in->enable_ns = enable;
3762 if (!in->standby)
3763 select_devices(in->dev, in->usecase);
3764 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003765 pthread_mutex_unlock(&in->dev->lock);
3766 pthread_mutex_unlock(&in->lock);
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 return 0;
3769}
3770
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003771static int in_add_audio_effect(const struct audio_stream *stream,
3772 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773{
Eric Laurent994a6932013-07-17 11:51:42 -07003774 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003775 return add_remove_audio_effect(stream, effect, true);
3776}
3777
3778static int in_remove_audio_effect(const struct audio_stream *stream,
3779 effect_handle_t effect)
3780{
Eric Laurent994a6932013-07-17 11:51:42 -07003781 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003782 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783}
3784
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303785int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786 audio_io_handle_t handle,
3787 audio_devices_t devices,
3788 audio_output_flags_t flags,
3789 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003790 struct audio_stream_out **stream_out,
3791 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792{
3793 struct audio_device *adev = (struct audio_device *)dev;
3794 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303795 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003796 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303799
3800 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3801 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003802 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303803 return -EINVAL;
3804 }
3805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3807
Mingming Yin3a941d42016-02-17 18:08:05 -08003808 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3809 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303810 devices, flags, &out->stream);
3811
3812
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003813 if (!out) {
3814 return -ENOMEM;
3815 }
3816
Haynes Mathew George204045b2015-02-25 20:32:03 -08003817 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003818 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003819 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 if (devices == AUDIO_DEVICE_NONE)
3822 devices = AUDIO_DEVICE_OUT_SPEAKER;
3823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 out->flags = flags;
3825 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003826 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003827 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003828 out->sample_rate = config->sample_rate;
3829 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3830 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003831 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003832 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003833 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303834 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835
Mingming Yin3a941d42016-02-17 18:08:05 -08003836 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3837 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3838 pthread_mutex_lock(&adev->lock);
3839 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3840 ret = read_hdmi_sink_caps(out);
3841 pthread_mutex_unlock(&adev->lock);
3842 if (ret != 0) {
3843 if (ret == -ENOSYS) {
3844 /* ignore and go with default */
3845 ret = 0;
3846 } else {
3847 ALOGE("error reading hdmi sink caps");
3848 goto error_open;
3849 }
3850 }
3851 }
3852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003854 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303855 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3856 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003857 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3858 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3859
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003860 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003861 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3862 /*
3863 * Do not handle stereo output in Multi-channel cases
3864 * Stereo case is handled in normal playback path
3865 */
3866 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3867 ret = AUDIO_CHANNEL_OUT_STEREO;
3868 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003869
3870 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3871 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003872 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003873 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003874 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003875
3876 if (config->sample_rate == 0)
3877 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3878 if (config->channel_mask == 0)
3879 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003880 if (config->format == 0)
3881 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003882
3883 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003884 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003885 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3887 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003889 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003891 } 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 -08003892 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003893 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003894 ret = voice_extn_compress_voip_open_output_stream(out);
3895 if (ret != 0) {
3896 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3897 __func__, ret);
3898 goto error_open;
3899 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003900 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3901 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3902
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003903 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3904 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3905 ALOGE("%s: Unsupported Offload information", __func__);
3906 ret = -EINVAL;
3907 goto error_open;
3908 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003909
Mingming Yin3a941d42016-02-17 18:08:05 -08003910 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003911 if(config->offload_info.format == 0)
3912 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003913 if (config->offload_info.sample_rate == 0)
3914 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003915 }
3916
Mingming Yin90310102013-11-13 16:57:00 -08003917 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303918 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003919 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003920 ret = -EINVAL;
3921 goto error_open;
3922 }
3923
3924 out->compr_config.codec = (struct snd_codec *)
3925 calloc(1, sizeof(struct snd_codec));
3926
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003927 if (!out->compr_config.codec) {
3928 ret = -ENOMEM;
3929 goto error_open;
3930 }
3931
vivek mehta0ea887a2015-08-26 14:01:20 -07003932 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303933 out->stream.pause = out_pause;
3934 out->stream.flush = out_flush;
3935 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003936 out->usecase = get_offload_usecase(adev, true);
3937 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003938 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003939 out->stream.set_callback = out_set_callback;
3940 out->stream.pause = out_pause;
3941 out->stream.resume = out_resume;
3942 out->stream.drain = out_drain;
3943 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003944 out->usecase = get_offload_usecase(adev, false);
3945 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003946 }
vivek mehta446c3962015-09-14 10:57:35 -07003947
3948 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003949 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3950 config->format == 0 && config->sample_rate == 0 &&
3951 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003952 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003953 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3954 } else {
3955 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3956 ret = -EEXIST;
3957 goto error_open;
3958 }
vivek mehta446c3962015-09-14 10:57:35 -07003959 }
3960
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003961 if (config->offload_info.channel_mask)
3962 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003963 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003965 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003966 } else {
3967 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3968 ret = -EINVAL;
3969 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003970 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003971
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003972 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003973 out->sample_rate = config->offload_info.sample_rate;
3974
Mingming Yin3ee55c62014-08-04 14:23:35 -07003975 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303977 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3978 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3979 audio_extn_dolby_send_ddp_endp_params(adev);
3980 audio_extn_dolby_set_dmid(adev);
3981 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003983 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003984 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003985 out->compr_config.codec->bit_rate =
3986 config->offload_info.bit_rate;
3987 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303988 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003989 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05303990 /* Update bit width only for non passthrough usecases.
3991 * For passthrough usecases, the output will always be opened @16 bit
3992 */
3993 if (!audio_extn_passthru_is_passthrough_stream(out))
3994 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003995 /*TODO: Do we need to change it for passthrough */
3996 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003997
Manish Dewangana6fc5442015-08-24 20:30:31 +05303998 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3999 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304000 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304001 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304002 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4003 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304004
4005 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4006 AUDIO_FORMAT_PCM) {
4007
4008 /*Based on platform support, configure appropriate alsa format for corresponding
4009 *hal input format.
4010 */
4011 out->compr_config.codec->format = hal_format_to_alsa(
4012 config->offload_info.format);
4013
Ashish Jain83a6cc22016-06-28 14:34:17 +05304014 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304015 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304016 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304017
4018 /*for direct PCM playback populate bit_width based on selected alsa format as
4019 *hal input format and alsa format might differ based on platform support.
4020 */
4021 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304022 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304023
4024 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4025
4026 /* Check if alsa session is configured with the same format as HAL input format,
4027 * if not then derive correct fragment size needed to accomodate the
4028 * conversion of HAL input format to alsa format.
4029 */
4030 audio_extn_utils_update_direct_pcm_fragment_size(out);
4031
4032 /*if hal input and output fragment size is different this indicates HAL input format is
4033 *not same as the alsa format
4034 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304035 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304036 /*Allocate a buffer to convert input data to the alsa configured format.
4037 *size of convert buffer is equal to the size required to hold one fragment size
4038 *worth of pcm data, this is because flinger does not write more than fragment_size
4039 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304040 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4041 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304042 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4043 ret = -ENOMEM;
4044 goto error_open;
4045 }
4046 }
4047 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4048 out->compr_config.fragment_size =
4049 audio_extn_passthru_get_buffer_size(&config->offload_info);
4050 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4051 } else {
4052 out->compr_config.fragment_size =
4053 platform_get_compress_offload_buffer_size(&config->offload_info);
4054 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4055 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004056
Amit Shekhar6f461b12014-08-01 14:52:58 -07004057 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304058 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004059
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304060 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4061 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4062 }
4063
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004064 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4065 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004066
Alexy Josephaa54c872014-12-03 02:46:47 -08004067
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004068 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304069 out->send_next_track_params = false;
4070 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004071 out->offload_state = OFFLOAD_STATE_IDLE;
4072 out->playback_started = 0;
4073
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004074 audio_extn_dts_create_state_notifier_node(out->usecase);
4075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004076 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4077 __func__, config->offload_info.version,
4078 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304079
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304080 /* Check if DSD audio format is supported in codec
4081 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304082 */
4083
4084 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304085 (!platform_check_codec_dsd_support(adev->platform) ||
4086 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304087 ret = -EINVAL;
4088 goto error_open;
4089 }
4090
Ashish Jain5106d362016-05-11 19:23:33 +05304091 /* Disable gapless if any of the following is true
4092 * passthrough playback
4093 * AV playback
4094 * Direct PCM playback
4095 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304096 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304097 (config->format == AUDIO_FORMAT_DSD) ||
4098 config->offload_info.has_video ||
4099 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304100 check_and_set_gapless_mode(adev, false);
4101 } else
4102 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004103
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304104 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004105 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4106 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304107 if (config->format == AUDIO_FORMAT_DSD) {
4108 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4109 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4110 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004111
4112 create_offload_callback_thread(out);
4113
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004114 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304115 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004116 if (ret != 0) {
4117 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4118 __func__, ret);
4119 goto error_open;
4120 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004121 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4122 if (config->sample_rate == 0)
4123 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4124 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4125 config->sample_rate != 8000) {
4126 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4127 ret = -EINVAL;
4128 goto error_open;
4129 }
4130 out->sample_rate = config->sample_rate;
4131 out->config.rate = config->sample_rate;
4132 if (config->format == AUDIO_FORMAT_DEFAULT)
4133 config->format = AUDIO_FORMAT_PCM_16_BIT;
4134 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4135 config->format = AUDIO_FORMAT_PCM_16_BIT;
4136 ret = -EINVAL;
4137 goto error_open;
4138 }
4139 out->format = config->format;
4140 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4141 out->config = pcm_config_afe_proxy_playback;
4142 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004143 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304144 unsigned int channels = 0;
4145 /*Update config params to default if not set by the caller*/
4146 if (config->sample_rate == 0)
4147 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4148 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4149 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4150 if (config->format == AUDIO_FORMAT_DEFAULT)
4151 config->format = AUDIO_FORMAT_PCM_16_BIT;
4152
4153 channels = audio_channel_count_from_out_mask(out->channel_mask);
4154
Ashish Jain83a6cc22016-06-28 14:34:17 +05304155 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4156 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004157 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4158 out->flags);
4159 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304160 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4161 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4162 out->config = pcm_config_low_latency;
4163 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4164 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4165 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304166 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4167 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4168 if (out->config.period_size <= 0) {
4169 ALOGE("Invalid configuration period size is not valid");
4170 ret = -EINVAL;
4171 goto error_open;
4172 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304173 } else {
4174 /* primary path is the default path selected if no other outputs are available/suitable */
4175 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4176 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4177 }
4178 out->hal_ip_format = format = out->format;
4179 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4180 out->hal_op_format = pcm_format_to_hal(out->config.format);
4181 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4182 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004183 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304184 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304185 if (out->hal_ip_format != out->hal_op_format) {
4186 uint32_t buffer_size = out->config.period_size *
4187 format_to_bitwidth_table[out->hal_op_format] *
4188 out->config.channels;
4189 out->convert_buffer = calloc(1, buffer_size);
4190 if (out->convert_buffer == NULL){
4191 ALOGE("Allocation failed for convert buffer for size %d",
4192 out->compr_config.fragment_size);
4193 ret = -ENOMEM;
4194 goto error_open;
4195 }
4196 ALOGD("Convert buffer allocated of size %d", buffer_size);
4197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 }
4199
Ashish Jain83a6cc22016-06-28 14:34:17 +05304200 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4201 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4202
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004203 /* TODO remove this hardcoding and check why width is zero*/
4204 if (out->bit_width == 0)
4205 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304206 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004207 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304208 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304209 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304210 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004211 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4212 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4213 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004214 if(adev->primary_output == NULL)
4215 adev->primary_output = out;
4216 else {
4217 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004218 ret = -EEXIST;
4219 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004220 }
4221 }
4222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 /* Check if this usecase is already existing */
4224 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004225 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4226 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004229 ret = -EEXIST;
4230 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231 }
4232 pthread_mutex_unlock(&adev->lock);
4233
4234 out->stream.common.get_sample_rate = out_get_sample_rate;
4235 out->stream.common.set_sample_rate = out_set_sample_rate;
4236 out->stream.common.get_buffer_size = out_get_buffer_size;
4237 out->stream.common.get_channels = out_get_channels;
4238 out->stream.common.get_format = out_get_format;
4239 out->stream.common.set_format = out_set_format;
4240 out->stream.common.standby = out_standby;
4241 out->stream.common.dump = out_dump;
4242 out->stream.common.set_parameters = out_set_parameters;
4243 out->stream.common.get_parameters = out_get_parameters;
4244 out->stream.common.add_audio_effect = out_add_audio_effect;
4245 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4246 out->stream.get_latency = out_get_latency;
4247 out->stream.set_volume = out_set_volume;
4248 out->stream.write = out_write;
4249 out->stream.get_render_position = out_get_render_position;
4250 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004251 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004253 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004255 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004256 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257
4258 config->format = out->stream.common.get_format(&out->stream.common);
4259 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4260 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4261
4262 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304263 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004264 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004265
4266 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4267 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4268 popcount(out->channel_mask), out->playback_started);
4269
Eric Laurent994a6932013-07-17 11:51:42 -07004270 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004272
4273error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304274 if (out->convert_buffer)
4275 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004276 free(out);
4277 *stream_out = NULL;
4278 ALOGD("%s: exit: ret %d", __func__, ret);
4279 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280}
4281
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304282void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 struct audio_stream_out *stream)
4284{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004285 struct stream_out *out = (struct stream_out *)stream;
4286 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004287 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004288
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304289 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4290
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004291 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304292 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004293 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304294 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004295 if(ret != 0)
4296 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4297 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004298 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004299 out_standby(&stream->common);
4300
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004301 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004302 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004303 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004304 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004305 if (out->compr_config.codec != NULL)
4306 free(out->compr_config.codec);
4307 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004308
Ashish Jain83a6cc22016-06-28 14:34:17 +05304309 if (out->convert_buffer != NULL) {
4310 free(out->convert_buffer);
4311 out->convert_buffer = NULL;
4312 }
4313
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004314 if (adev->voice_tx_output == out)
4315 adev->voice_tx_output = NULL;
4316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004317 pthread_cond_destroy(&out->cond);
4318 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004320 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321}
4322
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004323static void close_compress_sessions(struct audio_device *adev)
4324{
Mingming Yin7b762e72015-03-04 13:47:32 -08004325 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304326 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004327 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004328 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304329
4330 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004331 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304332 if (is_offload_usecase(usecase->id)) {
4333 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004334 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4335 out = usecase->stream.out;
4336 pthread_mutex_unlock(&adev->lock);
4337 out_standby(&out->stream.common);
4338 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004339 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004340 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304341 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004342 }
4343 pthread_mutex_unlock(&adev->lock);
4344}
4345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4347{
4348 struct audio_device *adev = (struct audio_device *)dev;
4349 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004351 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004352 int ret;
4353 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004355 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304358 if (!parms)
4359 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004360 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4361 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304362 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304363 if (strstr(snd_card_status, "OFFLINE")) {
4364 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304365 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004366 //close compress sessions on OFFLINE status
4367 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304368 } else if (strstr(snd_card_status, "ONLINE")) {
4369 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304370 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004371 //send dts hpx license if enabled
4372 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304373 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304374 }
4375
4376 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004377 status = voice_set_parameters(adev, parms);
4378 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004379 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004381 status = platform_set_parameters(adev->platform, parms);
4382 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004383 goto done;
4384
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004385 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4386 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004387 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4389 adev->bluetooth_nrec = true;
4390 else
4391 adev->bluetooth_nrec = false;
4392 }
4393
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004394 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4395 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4397 adev->screen_off = false;
4398 else
4399 adev->screen_off = true;
4400 }
4401
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004402 ret = str_parms_get_int(parms, "rotation", &val);
4403 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004404 bool reverse_speakers = false;
4405 switch(val) {
4406 // FIXME: note that the code below assumes that the speakers are in the correct placement
4407 // relative to the user when the device is rotated 90deg from its default rotation. This
4408 // assumption is device-specific, not platform-specific like this code.
4409 case 270:
4410 reverse_speakers = true;
4411 break;
4412 case 0:
4413 case 90:
4414 case 180:
4415 break;
4416 default:
4417 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004418 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004419 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004420 if (status == 0) {
4421 if (adev->speaker_lr_swap != reverse_speakers) {
4422 adev->speaker_lr_swap = reverse_speakers;
4423 // only update the selected device if there is active pcm playback
4424 struct audio_usecase *usecase;
4425 struct listnode *node;
4426 list_for_each(node, &adev->usecase_list) {
4427 usecase = node_to_item(node, struct audio_usecase, list);
4428 if (usecase->type == PCM_PLAYBACK) {
4429 select_devices(adev, usecase->id);
4430 break;
4431 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004432 }
4433 }
4434 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004435 }
4436
Mingming Yin514a8bc2014-07-29 15:22:21 -07004437 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4438 if (ret >= 0) {
4439 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4440 adev->bt_wb_speech_enabled = true;
4441 else
4442 adev->bt_wb_speech_enabled = false;
4443 }
4444
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004445 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4446 if (ret >= 0) {
4447 val = atoi(value);
4448 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004449 ALOGV("cache new ext disp type and edid");
4450 ret = platform_get_ext_disp_type(adev->platform);
4451 if (ret < 0) {
4452 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004453 status = ret;
4454 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004455 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004456 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004457 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004458 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004459 /*
4460 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4461 * Per AudioPolicyManager, USB device is higher priority than WFD.
4462 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4463 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4464 * starting voice call on USB
4465 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004466 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4467 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004468 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4469 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004470 }
vivek mehta344576a2016-04-12 18:56:03 -07004471 ALOGV("detected USB connect .. disable proxy");
4472 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004473 }
4474 }
4475
4476 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4477 if (ret >= 0) {
4478 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004479 /*
4480 * The HDMI / Displayport disconnect handling has been moved to
4481 * audio extension to ensure that its parameters are not
4482 * invalidated prior to updating sysfs of the disconnect event
4483 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4484 */
4485 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004486 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004487 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4488 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304489 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4490 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004491 }
vivek mehta344576a2016-04-12 18:56:03 -07004492 ALOGV("detected USB disconnect .. enable proxy");
4493 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004494 }
4495 }
4496
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304497 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4498 if (ret >= 0) {
4499 struct audio_usecase *usecase;
4500 struct listnode *node;
4501 list_for_each(node, &adev->usecase_list) {
4502 usecase = node_to_item(node, struct audio_usecase, list);
4503 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004504 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304505 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304506 lock_output_stream(usecase->stream.out);
4507 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304508 //force device switch to re configure encoder
4509 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304510 audio_extn_a2dp_set_handoff_mode(false);
4511 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304512 break;
4513 }
4514 }
4515 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304516 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004517done:
4518 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004519 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304520error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004521 ALOGV("%s: exit with code(%d)", __func__, status);
4522 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523}
4524
4525static char* adev_get_parameters(const struct audio_hw_device *dev,
4526 const char *keys)
4527{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004528 struct audio_device *adev = (struct audio_device *)dev;
4529 struct str_parms *reply = str_parms_create();
4530 struct str_parms *query = str_parms_create_str(keys);
4531 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304532 char value[256] = {0};
4533 int ret = 0;
4534
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004535 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004536 if (reply) {
4537 str_parms_destroy(reply);
4538 }
4539 if (query) {
4540 str_parms_destroy(query);
4541 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004542 ALOGE("adev_get_parameters: failed to create query or reply");
4543 return NULL;
4544 }
4545
Naresh Tannirud7205b62014-06-20 02:54:48 +05304546 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4547 sizeof(value));
4548 if (ret >=0) {
4549 int val = 1;
4550 pthread_mutex_lock(&adev->snd_card_status.lock);
4551 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4552 val = 0;
4553 pthread_mutex_unlock(&adev->snd_card_status.lock);
4554 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4555 goto exit;
4556 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004557
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004558 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004559 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004560 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004561 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304562 pthread_mutex_unlock(&adev->lock);
4563
Naresh Tannirud7205b62014-06-20 02:54:48 +05304564exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004565 str = str_parms_to_str(reply);
4566 str_parms_destroy(query);
4567 str_parms_destroy(reply);
4568
4569 ALOGV("%s: exit: returns - %s", __func__, str);
4570 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571}
4572
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004573static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574{
4575 return 0;
4576}
4577
4578static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4579{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004580 int ret;
4581 struct audio_device *adev = (struct audio_device *)dev;
4582 pthread_mutex_lock(&adev->lock);
4583 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004584 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004585 pthread_mutex_unlock(&adev->lock);
4586 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587}
4588
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004589static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4590 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591{
4592 return -ENOSYS;
4593}
4594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004595static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4596 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597{
4598 return -ENOSYS;
4599}
4600
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004601static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4602 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603{
4604 return -ENOSYS;
4605}
4606
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004607static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4608 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609{
4610 return -ENOSYS;
4611}
4612
4613static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4614{
4615 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 pthread_mutex_lock(&adev->lock);
4618 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004619 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004621 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004622 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004623 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004624 adev->current_call_output = NULL;
4625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626 }
4627 pthread_mutex_unlock(&adev->lock);
4628 return 0;
4629}
4630
4631static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4632{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004633 int ret;
4634
4635 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004636 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004637 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4638 pthread_mutex_unlock(&adev->lock);
4639
4640 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641}
4642
4643static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4644{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004645 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 return 0;
4647}
4648
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004649static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 const struct audio_config *config)
4651{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004652 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004654 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4655 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656}
4657
4658static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004659 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660 audio_devices_t devices,
4661 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004662 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304663 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004664 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004665 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666{
4667 struct audio_device *adev = (struct audio_device *)dev;
4668 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004669 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004670 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004671 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304672 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304675 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4676 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304678 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679
4680 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004681
4682 if (!in) {
4683 ALOGE("failed to allocate input stream");
4684 return -ENOMEM;
4685 }
4686
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304687 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304688 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4689 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004690 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004691 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 in->stream.common.get_sample_rate = in_get_sample_rate;
4694 in->stream.common.set_sample_rate = in_set_sample_rate;
4695 in->stream.common.get_buffer_size = in_get_buffer_size;
4696 in->stream.common.get_channels = in_get_channels;
4697 in->stream.common.get_format = in_get_format;
4698 in->stream.common.set_format = in_set_format;
4699 in->stream.common.standby = in_standby;
4700 in->stream.common.dump = in_dump;
4701 in->stream.common.set_parameters = in_set_parameters;
4702 in->stream.common.get_parameters = in_get_parameters;
4703 in->stream.common.add_audio_effect = in_add_audio_effect;
4704 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4705 in->stream.set_gain = in_set_gain;
4706 in->stream.read = in_read;
4707 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4708
4709 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004710 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712 in->standby = 1;
4713 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004714 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004715 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304717 in->usecase = USECASE_AUDIO_RECORD;
4718 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4719 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4720 is_low_latency = true;
4721#if LOW_LATENCY_CAPTURE_USE_CASE
4722 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4723#endif
4724 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4725 }
4726
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004727 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004728 if (in->realtime) {
4729 in->config = pcm_config_audio_capture_rt;
4730 in->sample_rate = in->config.rate;
4731 in->af_period_multiplier = af_period_multiplier;
4732 } else {
4733 in->config = pcm_config_audio_capture;
4734 in->config.rate = config->sample_rate;
4735 in->sample_rate = config->sample_rate;
4736 in->af_period_multiplier = 1;
4737 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304738 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304740 /* restrict 24 bit capture for unprocessed source only
4741 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4742 */
4743 if (config->format == AUDIO_FORMAT_DEFAULT) {
4744 config->format = AUDIO_FORMAT_PCM_16_BIT;
4745 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4746 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4747 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4748 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4749 bool ret_error = false;
4750 in->bit_width = 24;
4751 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4752 from HAL is 24_packed and 8_24
4753 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4754 24_packed return error indicating supported format is 24_packed
4755 *> In case of any other source requesting 24 bit or float return error
4756 indicating format supported is 16 bit only.
4757
4758 on error flinger will retry with supported format passed
4759 */
4760 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4761 (source != AUDIO_SOURCE_CAMCORDER)) {
4762 config->format = AUDIO_FORMAT_PCM_16_BIT;
4763 if (config->sample_rate > 48000)
4764 config->sample_rate = 48000;
4765 ret_error = true;
4766 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4767 in->config.format = PCM_FORMAT_S24_3LE;
4768 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4769 in->config.format = PCM_FORMAT_S24_LE;
4770 } else {
4771 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4772 ret_error = true;
4773 }
4774
4775 if (ret_error) {
4776 ret = -EINVAL;
4777 goto err_open;
4778 }
4779 }
4780
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304781 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304782 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4783 (adev->mode != AUDIO_MODE_IN_CALL)) {
4784 ret = -EINVAL;
4785 goto err_open;
4786 }
4787
4788 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4789 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004790 if (config->sample_rate == 0)
4791 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4792 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4793 config->sample_rate != 8000) {
4794 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4795 ret = -EINVAL;
4796 goto err_open;
4797 }
4798 if (config->format == AUDIO_FORMAT_DEFAULT)
4799 config->format = AUDIO_FORMAT_PCM_16_BIT;
4800 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4801 config->format = AUDIO_FORMAT_PCM_16_BIT;
4802 ret = -EINVAL;
4803 goto err_open;
4804 }
4805
4806 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4807 in->config = pcm_config_afe_proxy_record;
4808 in->config.channels = channel_count;
4809 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304810 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304811 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4812 in, config, &channel_mask_updated)) {
4813 if (channel_mask_updated == true) {
4814 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4815 __func__, config->channel_mask);
4816 ret = -EINVAL;
4817 goto err_open;
4818 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304819 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004820 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004821 audio_extn_compr_cap_format_supported(config->format) &&
4822 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004823 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304824 } else if (audio_extn_cin_applicable_stream(in)) {
4825 ret = audio_extn_cin_configure_input_stream(in);
4826 if (ret)
4827 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004828 } else {
4829 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004830 if (!in->realtime) {
4831 in->format = config->format;
4832 frame_size = audio_stream_in_frame_size(&in->stream);
4833 buffer_size = get_input_buffer_size(config->sample_rate,
4834 config->format,
4835 channel_count,
4836 is_low_latency);
4837 in->config.period_size = buffer_size / frame_size;
4838 }
4839
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004840 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004841 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004842 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004843 (in->config.rate == 8000 || in->config.rate == 16000 ||
4844 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004845 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4846 voice_extn_compress_voip_open_input_stream(in);
4847 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304850 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4851 &adev->streams_input_cfg_list,
4852 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304853 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304854
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004855 /* This stream could be for sound trigger lab,
4856 get sound trigger pcm if present */
4857 audio_extn_sound_trigger_check_and_get_session(in);
4858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004860 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004861 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862
4863err_open:
4864 free(in);
4865 *stream_in = NULL;
4866 return ret;
4867}
4868
4869static void adev_close_input_stream(struct audio_hw_device *dev,
4870 struct audio_stream_in *stream)
4871{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004872 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004873 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004874 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304875
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304876 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004877
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304878 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004879 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304880
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004881 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304882 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004883 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304884 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004885 if (ret != 0)
4886 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4887 __func__, ret);
4888 } else
4889 in_standby(&stream->common);
4890
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004891 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004892 audio_extn_ssr_deinit();
4893 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304895 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004896 audio_extn_compr_cap_format_supported(in->config.format))
4897 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304898
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304899 if (audio_extn_cin_attached_usecase(in->usecase))
4900 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004901
Mingming Yinfd7607b2016-01-22 12:48:44 -08004902 if (in->is_st_session) {
4903 ALOGV("%s: sound trigger pcm stop lab", __func__);
4904 audio_extn_sound_trigger_stop_lab(in);
4905 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004906 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907 return;
4908}
4909
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004910static int adev_dump(const audio_hw_device_t *device __unused,
4911 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912{
4913 return 0;
4914}
4915
4916static int adev_close(hw_device_t *device)
4917{
4918 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004919
4920 if (!adev)
4921 return 0;
4922
4923 pthread_mutex_lock(&adev_init_lock);
4924
4925 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004926 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004927 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304928 audio_extn_utils_release_streams_cfg_lists(
4929 &adev->streams_output_cfg_list,
4930 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304931 if (audio_extn_qaf_is_enabled())
4932 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004933 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004934 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004935 free(adev->snd_dev_ref_cnt);
4936 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004937 if (adev->adm_deinit)
4938 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304939 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004940 free(device);
4941 adev = NULL;
4942 }
4943 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945 return 0;
4946}
4947
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004948/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4949 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4950 * just that it _might_ work.
4951 */
4952static int period_size_is_plausible_for_low_latency(int period_size)
4953{
4954 switch (period_size) {
4955 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004956 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004957 case 240:
4958 case 320:
4959 case 480:
4960 return 1;
4961 default:
4962 return 0;
4963 }
4964}
4965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966static int adev_open(const hw_module_t *module, const char *name,
4967 hw_device_t **device)
4968{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304969 int ret;
4970
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004971 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4973
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004974 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004975 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004976 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004977 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004978 ALOGD("%s: returning existing instance of adev", __func__);
4979 ALOGD("%s: exit", __func__);
4980 pthread_mutex_unlock(&adev_init_lock);
4981 return 0;
4982 }
4983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984 adev = calloc(1, sizeof(struct audio_device));
4985
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004986 if (!adev) {
4987 pthread_mutex_unlock(&adev_init_lock);
4988 return -ENOMEM;
4989 }
4990
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004991 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4994 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4995 adev->device.common.module = (struct hw_module_t *)module;
4996 adev->device.common.close = adev_close;
4997
4998 adev->device.init_check = adev_init_check;
4999 adev->device.set_voice_volume = adev_set_voice_volume;
5000 adev->device.set_master_volume = adev_set_master_volume;
5001 adev->device.get_master_volume = adev_get_master_volume;
5002 adev->device.set_master_mute = adev_set_master_mute;
5003 adev->device.get_master_mute = adev_get_master_mute;
5004 adev->device.set_mode = adev_set_mode;
5005 adev->device.set_mic_mute = adev_set_mic_mute;
5006 adev->device.get_mic_mute = adev_get_mic_mute;
5007 adev->device.set_parameters = adev_set_parameters;
5008 adev->device.get_parameters = adev_get_parameters;
5009 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5010 adev->device.open_output_stream = adev_open_output_stream;
5011 adev->device.close_output_stream = adev_close_output_stream;
5012 adev->device.open_input_stream = adev_open_input_stream;
5013 adev->device.close_input_stream = adev_close_input_stream;
5014 adev->device.dump = adev_dump;
5015
5016 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005018 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005019 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005020 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005022 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005023 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005024 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005025 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005026 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005027 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005028 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005029 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305030 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305031 adev->perf_lock_opts[0] = 0x101;
5032 adev->perf_lock_opts[1] = 0x20E;
5033 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305034
5035 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5036 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005038 adev->platform = platform_init(adev);
5039 if (!adev->platform) {
5040 free(adev->snd_dev_ref_cnt);
5041 free(adev);
5042 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5043 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005044 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305045 pthread_mutex_destroy(&adev->lock);
5046 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005047 return -EINVAL;
5048 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005049
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305050 if (audio_extn_qaf_is_enabled()) {
5051 ret = audio_extn_qaf_init(adev);
5052 if (ret < 0) {
5053 free(adev);
5054 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5055 *device = NULL;
5056 pthread_mutex_unlock(&adev_init_lock);
5057 pthread_mutex_destroy(&adev->lock);
5058 return ret;
5059 }
5060
5061 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5062 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5063 }
5064
Naresh Tanniru4c630392014-05-12 01:05:52 +05305065 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5066
Eric Laurentc4aef752013-09-12 17:45:53 -07005067 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5068 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5069 if (adev->visualizer_lib == NULL) {
5070 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5071 } else {
5072 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5073 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005074 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005075 "visualizer_hal_start_output");
5076 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005077 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005078 "visualizer_hal_stop_output");
5079 }
5080 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305081 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005082 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005083 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005084 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005085
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005086 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5087 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5088 if (adev->offload_effects_lib == NULL) {
5089 ALOGE("%s: DLOPEN failed for %s", __func__,
5090 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5091 } else {
5092 ALOGV("%s: DLOPEN successful for %s", __func__,
5093 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5094 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305095 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005096 "offload_effects_bundle_hal_start_output");
5097 adev->offload_effects_stop_output =
5098 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5099 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005100 adev->offload_effects_set_hpx_state =
5101 (int (*)(bool))dlsym(adev->offload_effects_lib,
5102 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305103 adev->offload_effects_get_parameters =
5104 (void (*)(struct str_parms *, struct str_parms *))
5105 dlsym(adev->offload_effects_lib,
5106 "offload_effects_bundle_get_parameters");
5107 adev->offload_effects_set_parameters =
5108 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5109 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005110 }
5111 }
5112
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005113 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5114 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5115 if (adev->adm_lib == NULL) {
5116 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5117 } else {
5118 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5119 adev->adm_init = (adm_init_t)
5120 dlsym(adev->adm_lib, "adm_init");
5121 adev->adm_deinit = (adm_deinit_t)
5122 dlsym(adev->adm_lib, "adm_deinit");
5123 adev->adm_register_input_stream = (adm_register_input_stream_t)
5124 dlsym(adev->adm_lib, "adm_register_input_stream");
5125 adev->adm_register_output_stream = (adm_register_output_stream_t)
5126 dlsym(adev->adm_lib, "adm_register_output_stream");
5127 adev->adm_deregister_stream = (adm_deregister_stream_t)
5128 dlsym(adev->adm_lib, "adm_deregister_stream");
5129 adev->adm_request_focus = (adm_request_focus_t)
5130 dlsym(adev->adm_lib, "adm_request_focus");
5131 adev->adm_abandon_focus = (adm_abandon_focus_t)
5132 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005133 adev->adm_set_config = (adm_set_config_t)
5134 dlsym(adev->adm_lib, "adm_set_config");
5135 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5136 dlsym(adev->adm_lib, "adm_request_focus_v2");
5137 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5138 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5139 adev->adm_on_routing_change = (adm_on_routing_change_t)
5140 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005141 }
5142 }
5143
Mingming Yin514a8bc2014-07-29 15:22:21 -07005144 adev->bt_wb_speech_enabled = false;
5145
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005146 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147 *device = &adev->device.common;
5148
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305149 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5150 &adev->streams_output_cfg_list,
5151 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005152
Kiran Kandi910e1862013-10-29 13:29:42 -07005153 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005154
5155 char value[PROPERTY_VALUE_MAX];
5156 int trial;
5157 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5158 trial = atoi(value);
5159 if (period_size_is_plausible_for_low_latency(trial)) {
5160 pcm_config_low_latency.period_size = trial;
5161 pcm_config_low_latency.start_threshold = trial / 4;
5162 pcm_config_low_latency.avail_min = trial / 4;
5163 configured_low_latency_capture_period_size = trial;
5164 }
5165 }
5166 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5167 trial = atoi(value);
5168 if (period_size_is_plausible_for_low_latency(trial)) {
5169 configured_low_latency_capture_period_size = trial;
5170 }
5171 }
5172
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005173 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5174 af_period_multiplier = atoi(value);
5175 if (af_period_multiplier < 0)
5176 af_period_multiplier = 2;
5177 else if (af_period_multiplier > 4)
5178 af_period_multiplier = 4;
5179
5180 ALOGV("new period_multiplier = %d", af_period_multiplier);
5181 }
5182
vivek mehta446c3962015-09-14 10:57:35 -07005183 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005184 pthread_mutex_unlock(&adev_init_lock);
5185
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005186 if (adev->adm_init)
5187 adev->adm_data = adev->adm_init();
5188
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305189 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305190 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005191 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 return 0;
5193}
5194
5195static struct hw_module_methods_t hal_module_methods = {
5196 .open = adev_open,
5197};
5198
5199struct audio_module HAL_MODULE_INFO_SYM = {
5200 .common = {
5201 .tag = HARDWARE_MODULE_TAG,
5202 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5203 .hal_api_version = HARDWARE_HAL_API_VERSION,
5204 .id = AUDIO_HARDWARE_MODULE_ID,
5205 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005206 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207 .methods = &hal_module_methods,
5208 },
5209};